Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock1
-rw-r--r--crates/hir-def/src/expr_store/path.rs2
-rw-r--r--crates/hir-ty/src/autoderef.rs56
-rw-r--r--crates/hir-ty/src/builder.rs16
-rw-r--r--crates/hir-ty/src/chalk_db.rs15
-rw-r--r--crates/hir-ty/src/consteval.rs102
-rw-r--r--crates/hir-ty/src/consteval/tests.rs8
-rw-r--r--crates/hir-ty/src/consteval_nextsolver.rs20
-rw-r--r--crates/hir-ty/src/db.rs72
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs46
-rw-r--r--crates/hir-ty/src/diagnostics/match_check.rs37
-rw-r--r--crates/hir-ty/src/diagnostics/unsafe_check.rs24
-rw-r--r--crates/hir-ty/src/display.rs11
-rw-r--r--crates/hir-ty/src/drop.rs13
-rw-r--r--crates/hir-ty/src/infer.rs1246
-rw-r--r--crates/hir-ty/src/infer/autoderef.rs14
-rw-r--r--crates/hir-ty/src/infer/cast.rs347
-rw-r--r--crates/hir-ty/src/infer/closure.rs78
-rw-r--r--crates/hir-ty/src/infer/closure/analysis.rs264
-rw-r--r--crates/hir-ty/src/infer/coerce.rs240
-rw-r--r--crates/hir-ty/src/infer/diagnostics.rs46
-rw-r--r--crates/hir-ty/src/infer/expr.rs1244
-rw-r--r--crates/hir-ty/src/infer/fallback.rs4
-rw-r--r--crates/hir-ty/src/infer/mutability.rs43
-rw-r--r--crates/hir-ty/src/infer/pat.rs323
-rw-r--r--crates/hir-ty/src/infer/path.rs217
-rw-r--r--crates/hir-ty/src/infer/unify.rs964
-rw-r--r--crates/hir-ty/src/layout.rs17
-rw-r--r--crates/hir-ty/src/layout/tests.rs13
-rw-r--r--crates/hir-ty/src/lib.rs123
-rw-r--r--crates/hir-ty/src/lower.rs38
-rw-r--r--crates/hir-ty/src/lower/path.rs190
-rw-r--r--crates/hir-ty/src/lower_nextsolver.rs176
-rw-r--r--crates/hir-ty/src/lower_nextsolver/path.rs57
-rw-r--r--crates/hir-ty/src/method_resolution.rs740
-rw-r--r--crates/hir-ty/src/mir.rs6
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs29
-rw-r--r--crates/hir-ty/src/mir/eval.rs226
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs33
-rw-r--r--crates/hir-ty/src/mir/eval/shim/simd.rs6
-rw-r--r--crates/hir-ty/src/mir/eval/tests.rs4
-rw-r--r--crates/hir-ty/src/mir/lower.rs196
-rw-r--r--crates/hir-ty/src/mir/lower/as_place.rs33
-rw-r--r--crates/hir-ty/src/mir/lower/pattern_matching.rs69
-rw-r--r--crates/hir-ty/src/mir/lower/tests.rs11
-rw-r--r--crates/hir-ty/src/mir/monomorphization.rs44
-rw-r--r--crates/hir-ty/src/next_solver.rs3
-rw-r--r--crates/hir-ty/src/next_solver/def_id.rs11
-rw-r--r--crates/hir-ty/src/next_solver/fold.rs23
-rw-r--r--crates/hir-ty/src/next_solver/generic_arg.rs68
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs116
-rw-r--r--crates/hir-ty/src/next_solver/infer/resolve.rs52
-rw-r--r--crates/hir-ty/src/next_solver/infer/select.rs78
-rw-r--r--crates/hir-ty/src/next_solver/infer/snapshot/mod.rs13
-rw-r--r--crates/hir-ty/src/next_solver/infer/traits.rs36
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs4
-rw-r--r--crates/hir-ty/src/next_solver/mapping.rs40
-rw-r--r--crates/hir-ty/src/next_solver/region.rs12
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs67
-rw-r--r--crates/hir-ty/src/next_solver/util.rs2
-rw-r--r--crates/hir-ty/src/tests.rs512
-rw-r--r--crates/hir-ty/src/tests/closure_captures.rs15
-rw-r--r--crates/hir-ty/src/tests/coercion.rs16
-rw-r--r--crates/hir-ty/src/tests/display_source_code.rs8
-rw-r--r--crates/hir-ty/src/tests/incremental.rs19
-rw-r--r--crates/hir-ty/src/tests/macros.rs8
-rw-r--r--crates/hir-ty/src/tests/method_resolution.rs6
-rw-r--r--crates/hir-ty/src/tests/opaque_types.rs1
-rw-r--r--crates/hir-ty/src/tests/regression.rs8
-rw-r--r--crates/hir-ty/src/tests/regression/new_solver.rs2
-rw-r--r--crates/hir-ty/src/tests/simple.rs35
-rw-r--r--crates/hir-ty/src/tests/traits.rs54
-rw-r--r--crates/hir-ty/src/traits.rs35
-rw-r--r--crates/hir/src/diagnostics.rs29
-rw-r--r--crates/hir/src/lib.rs74
-rw-r--r--crates/hir/src/semantics.rs32
-rw-r--r--crates/hir/src/source_analyzer.rs188
-rw-r--r--crates/ide-assists/src/handlers/convert_closure_to_fn.rs2
-rw-r--r--crates/ide-completion/src/render.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/type_mismatch.rs2
-rw-r--r--crates/ide-ssr/src/matching.rs60
-rw-r--r--crates/ide-ssr/src/tests.rs146
-rw-r--r--crates/ide/src/inlay_hints/bind_pat.rs4
-rw-r--r--crates/ide/src/interpret.rs2
-rw-r--r--crates/ide/src/static_index.rs111
-rw-r--r--crates/ide/src/syntax_highlighting.rs9
-rw-r--r--crates/ide/src/view_memory_layout.rs26
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs61
-rw-r--r--crates/rust-analyzer/src/lib.rs2
90 files changed, 4558 insertions, 4902 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 086f38f06a..5a0d209602 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2040,6 +2040,7 @@ dependencies = [
"process-wrap",
"profile",
"project-model",
+ "ra-ap-rustc_type_ir",
"rayon",
"rustc-hash 2.1.1",
"scip",
diff --git a/crates/hir-def/src/expr_store/path.rs b/crates/hir-def/src/expr_store/path.rs
index 55e738b58b..fbbaa587b0 100644
--- a/crates/hir-def/src/expr_store/path.rs
+++ b/crates/hir-def/src/expr_store/path.rs
@@ -88,7 +88,7 @@ pub struct AssociatedTypeBinding {
}
/// A single generic argument.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GenericArg {
Type(TypeRefId),
Lifetime(LifetimeRefId),
diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs
index 21a86d3e43..0be00afe7b 100644
--- a/crates/hir-ty/src/autoderef.rs
+++ b/crates/hir-ty/src/autoderef.rs
@@ -5,12 +5,15 @@
use std::fmt;
+use hir_def::TraitId;
use hir_def::{TypeAliasId, lang_item::LangItem};
use rustc_type_ir::inherent::{IntoKind, Ty as _};
use tracing::debug;
use triomphe::Arc;
+use crate::next_solver::TraitRef;
use crate::next_solver::infer::InferOk;
+use crate::next_solver::infer::traits::Obligation;
use crate::{
TraitEnvironment,
db::HirDatabase,
@@ -38,14 +41,14 @@ pub fn autoderef<'db>(
ty: crate::Canonical<crate::Ty>,
) -> impl Iterator<Item = crate::Ty> + use<> {
let mut table = InferenceTable::new(db, env);
- let interner = table.interner;
- let ty = table.instantiate_canonical(ty);
- let mut autoderef = Autoderef::new_no_tracking(&mut table, ty.to_nextsolver(interner));
+ let interner = table.interner();
+ let ty = table.instantiate_canonical(ty.to_nextsolver(interner));
+ let mut autoderef = Autoderef::new_no_tracking(&mut table, ty);
let mut v = Vec::new();
while let Some((ty, _steps)) = autoderef.next() {
// `ty` may contain unresolved inference variables. Since there's no chance they would be
// resolved, just replace with fallback type.
- let resolved = autoderef.table.resolve_completely(ty.to_chalk(interner));
+ let resolved = autoderef.table.resolve_completely(ty).to_chalk(interner);
// If the deref chain contains a cycle (e.g. `A` derefs to `B` and `B` derefs to `A`), we
// would revisit some already visited types. Stop here to avoid duplication.
@@ -101,6 +104,7 @@ struct AutoderefSnapshot<'db, Steps> {
#[derive(Clone, Copy)]
struct AutoderefTraits {
+ trait_: TraitId,
trait_target: TypeAliasId,
}
@@ -215,16 +219,26 @@ impl<'a, 'db, Steps: TrackAutoderefSteps<'db>> Autoderef<'a, 'db, Steps> {
Some(it) => Some(*it),
None => {
let traits = if self.use_receiver_trait {
- AutoderefTraits {
- trait_target: LangItem::ReceiverTarget
- .resolve_type_alias(self.table.db, self.table.trait_env.krate)
- .or_else(|| {
- LangItem::DerefTarget
- .resolve_type_alias(self.table.db, self.table.trait_env.krate)
- })?,
- }
+ (|| {
+ Some(AutoderefTraits {
+ trait_: LangItem::Receiver
+ .resolve_trait(self.table.db, self.table.trait_env.krate)?,
+ trait_target: LangItem::ReceiverTarget
+ .resolve_type_alias(self.table.db, self.table.trait_env.krate)?,
+ })
+ })()
+ .or_else(|| {
+ Some(AutoderefTraits {
+ trait_: LangItem::Deref
+ .resolve_trait(self.table.db, self.table.trait_env.krate)?,
+ trait_target: LangItem::DerefTarget
+ .resolve_type_alias(self.table.db, self.table.trait_env.krate)?,
+ })
+ })?
} else {
AutoderefTraits {
+ trait_: LangItem::Deref
+ .resolve_trait(self.table.db, self.table.trait_env.krate)?,
trait_target: LangItem::DerefTarget
.resolve_type_alias(self.table.db, self.table.trait_env.krate)?,
}
@@ -236,10 +250,22 @@ impl<'a, 'db, Steps: TrackAutoderefSteps<'db>> Autoderef<'a, 'db, Steps> {
fn overloaded_deref_ty(&mut self, ty: Ty<'db>) -> Option<Ty<'db>> {
debug!("overloaded_deref_ty({:?})", ty);
- let interner = self.table.interner;
+ let interner = self.table.interner();
// <ty as Deref>, or whatever the equivalent trait is that we've been asked to walk.
- let AutoderefTraits { trait_target } = self.autoderef_traits()?;
+ let AutoderefTraits { trait_, trait_target } = self.autoderef_traits()?;
+
+ let trait_ref = TraitRef::new(interner, trait_.into(), [ty]);
+ let obligation =
+ Obligation::new(interner, ObligationCause::new(), self.table.trait_env.env, trait_ref);
+ // We detect whether the self type implements `Deref` before trying to
+ // structurally normalize. We use `predicate_may_hold_opaque_types_jank`
+ // to support not-yet-defined opaque types. It will succeed for `impl Deref`
+ // but fail for `impl OtherTrait`.
+ if !self.table.infer_ctxt.predicate_may_hold_opaque_types_jank(&obligation) {
+ debug!("overloaded_deref_ty: cannot match obligation");
+ return None;
+ }
let (normalized_ty, obligations) = structurally_normalize_ty(
self.table,
@@ -316,7 +342,7 @@ pub(crate) fn overloaded_deref_ty<'db>(
table: &InferenceTable<'db>,
ty: Ty<'db>,
) -> Option<InferOk<'db, Ty<'db>>> {
- let interner = table.interner;
+ let interner = table.interner();
let trait_target = LangItem::DerefTarget.resolve_type_alias(table.db, table.trait_env.krate)?;
diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs
index 5511587c71..798b0f2c0c 100644
--- a/crates/hir-ty/src/builder.rs
+++ b/crates/hir-ty/src/builder.rs
@@ -15,7 +15,10 @@ use crate::{
error_lifetime,
generics::generics,
infer::unify::InferenceTable,
- next_solver::{DbInterner, EarlyBinder, mapping::ChalkToNextSolver},
+ next_solver::{
+ DbInterner, EarlyBinder,
+ mapping::{ChalkToNextSolver, NextSolverToChalk},
+ },
primitive, to_assoc_type_id, to_chalk_trait_id,
};
@@ -141,10 +144,13 @@ impl<D> TyBuilder<D> {
#[tracing::instrument(skip_all)]
pub(crate) fn fill_with_inference_vars(self, table: &mut InferenceTable<'_>) -> Self {
- self.fill(|x| match x {
- ParamKind::Type => table.new_type_var().cast(Interner),
- ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
- ParamKind::Lifetime => table.new_lifetime_var().cast(Interner),
+ 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())
})
}
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index 546991cf65..3d06b52106 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -2,7 +2,7 @@
//! about the code that Chalk needs.
use hir_def::{CallableDefId, GenericDefId};
-use crate::{Interner, Substitution, db::HirDatabase, mapping::from_chalk};
+use crate::{Interner, db::HirDatabase, mapping::from_chalk};
pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
@@ -53,16 +53,3 @@ pub(crate) fn adt_variance_query(db: &dyn HirDatabase, adt_id: hir_def::AdtId) -
}),
)
}
-
-/// Returns instantiated predicates.
-pub(super) fn convert_where_clauses(
- db: &dyn HirDatabase,
- def: GenericDefId,
- substs: &Substitution,
-) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> {
- db.generic_predicates(def)
- .iter()
- .cloned()
- .map(|pred| pred.substitute(Interner, substs))
- .collect()
-}
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index b2daed425e..8b12c5fd89 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -4,8 +4,8 @@ use base_db::Crate;
use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast};
use hir_def::{
EnumVariantId, GeneralConstId, HasModule as _, StaticId,
- expr_store::{Body, HygieneId, path::Path},
- hir::{Expr, ExprId},
+ expr_store::{HygieneId, path::Path},
+ hir::Expr,
resolver::{Resolver, ValueNs},
type_ref::LiteralConstRef,
};
@@ -19,13 +19,12 @@ use crate::{
db::HirDatabase,
display::DisplayTarget,
generics::Generics,
- infer::InferenceContext,
lower::ParamLoweringMode,
next_solver::{DbInterner, mapping::ChalkToNextSolver},
to_placeholder_idx,
};
-use super::mir::{MirEvalError, MirLowerError, interpret_mir, lower_to_mir, pad16};
+use super::mir::{MirEvalError, MirLowerError, interpret_mir, pad16};
/// Extension trait for [`Const`]
pub trait ConstExt {
@@ -56,12 +55,12 @@ impl ConstExt for Const {
}
#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum ConstEvalError {
- MirLowerError(MirLowerError),
- MirEvalError(MirEvalError),
+pub enum ConstEvalError<'db> {
+ MirLowerError(MirLowerError<'db>),
+ MirEvalError(MirEvalError<'db>),
}
-impl ConstEvalError {
+impl ConstEvalError<'_> {
pub fn pretty_print(
&self,
f: &mut String,
@@ -80,8 +79,8 @@ impl ConstEvalError {
}
}
-impl From<MirLowerError> for ConstEvalError {
- fn from(value: MirLowerError) -> Self {
+impl<'db> From<MirLowerError<'db>> for ConstEvalError<'db> {
+ fn from(value: MirLowerError<'db>) -> Self {
match value {
MirLowerError::ConstEvalError(_, e) => *e,
_ => ConstEvalError::MirLowerError(value),
@@ -89,8 +88,8 @@ impl From<MirLowerError> for ConstEvalError {
}
}
-impl From<MirEvalError> for ConstEvalError {
- fn from(value: MirEvalError) -> Self {
+impl<'db> From<MirEvalError<'db>> for ConstEvalError<'db> {
+ fn from(value: MirEvalError<'db>) -> Self {
ConstEvalError::MirEvalError(value)
}
}
@@ -225,35 +224,35 @@ pub fn try_const_isize(db: &dyn HirDatabase, c: &Const) -> Option<i128> {
}
}
-pub(crate) fn const_eval_cycle_result(
- _: &dyn HirDatabase,
+pub(crate) fn const_eval_cycle_result<'db>(
+ _: &'db dyn HirDatabase,
_: GeneralConstId,
_: Substitution,
- _: Option<Arc<TraitEnvironment<'_>>>,
-) -> Result<Const, ConstEvalError> {
+ _: Option<Arc<TraitEnvironment<'db>>>,
+) -> Result<Const, ConstEvalError<'db>> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}
-pub(crate) fn const_eval_static_cycle_result(
- _: &dyn HirDatabase,
+pub(crate) fn const_eval_static_cycle_result<'db>(
+ _: &'db dyn HirDatabase,
_: StaticId,
-) -> Result<Const, ConstEvalError> {
+) -> Result<Const, ConstEvalError<'db>> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}
-pub(crate) fn const_eval_discriminant_cycle_result(
- _: &dyn HirDatabase,
+pub(crate) fn const_eval_discriminant_cycle_result<'db>(
+ _: &'db dyn HirDatabase,
_: EnumVariantId,
-) -> Result<i128, ConstEvalError> {
+) -> Result<i128, ConstEvalError<'db>> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}
-pub(crate) fn const_eval_query(
- db: &dyn HirDatabase,
+pub(crate) fn const_eval_query<'db>(
+ db: &'db dyn HirDatabase,
def: GeneralConstId,
subst: Substitution,
- trait_env: Option<Arc<TraitEnvironment<'_>>>,
-) -> Result<Const, ConstEvalError> {
+ trait_env: Option<Arc<TraitEnvironment<'db>>>,
+) -> Result<Const, ConstEvalError<'db>> {
let body = match def {
GeneralConstId::ConstId(c) => {
db.monomorphized_mir_body(c.into(), subst, db.trait_environment(c.into()))?
@@ -267,10 +266,10 @@ pub(crate) fn const_eval_query(
Ok(c)
}
-pub(crate) fn const_eval_static_query(
- db: &dyn HirDatabase,
+pub(crate) fn const_eval_static_query<'db>(
+ db: &'db dyn HirDatabase,
def: StaticId,
-) -> Result<Const, ConstEvalError> {
+) -> Result<Const, ConstEvalError<'db>> {
let body = db.monomorphized_mir_body(
def.into(),
Substitution::empty(Interner),
@@ -280,10 +279,10 @@ pub(crate) fn const_eval_static_query(
Ok(c)
}
-pub(crate) fn const_eval_discriminant_variant(
- db: &dyn HirDatabase,
+pub(crate) fn const_eval_discriminant_variant<'db>(
+ db: &'db dyn HirDatabase,
variant_id: EnumVariantId,
-) -> Result<i128, ConstEvalError> {
+) -> Result<i128, ConstEvalError<'db>> {
let def = variant_id.into();
let body = db.body(def);
let loc = variant_id.lookup(db);
@@ -317,44 +316,5 @@ pub(crate) fn const_eval_discriminant_variant(
Ok(c)
}
-// FIXME: Ideally constants in const eval should have separate body (issue #7434), and this function should
-// get an `InferenceResult` instead of an `InferenceContext`. And we should remove `ctx.clone().resolve_all()` here
-// and make this function private. See the fixme comment on `InferenceContext::resolve_all`.
-pub(crate) fn eval_to_const(
- expr: ExprId,
- mode: ParamLoweringMode,
- ctx: &mut InferenceContext<'_>,
- debruijn: DebruijnIndex,
-) -> Const {
- let db = ctx.db;
- let infer = ctx.fixme_resolve_all_clone();
- fn has_closure(body: &Body, expr: ExprId) -> bool {
- if matches!(body[expr], Expr::Closure { .. }) {
- return true;
- }
- let mut r = false;
- body.walk_child_exprs(expr, |idx| r |= has_closure(body, idx));
- r
- }
- if has_closure(ctx.body, expr) {
- // Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic.
- return unknown_const(infer[expr].clone());
- }
- if let Expr::Path(p) = &ctx.body[expr] {
- let resolver = &ctx.resolver;
- if let Some(c) =
- path_to_const(db, resolver, p, mode, || ctx.generics(), debruijn, infer[expr].clone())
- {
- return c;
- }
- }
- if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr)
- && let Ok((Ok(result), _)) = interpret_mir(db, Arc::new(mir_body), true, None)
- {
- return result;
- }
- unknown_const(infer[expr].clone())
-}
-
#[cfg(test)]
mod tests;
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 1586846bbe..5a214eabcd 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -21,7 +21,7 @@ use super::{
mod intrinsics;
-fn simplify(e: ConstEvalError) -> ConstEvalError {
+fn simplify(e: ConstEvalError<'_>) -> ConstEvalError<'_> {
match e {
ConstEvalError::MirEvalError(MirEvalError::InFunction(e, _)) => {
simplify(ConstEvalError::MirEvalError(*e))
@@ -33,7 +33,7 @@ fn simplify(e: ConstEvalError) -> ConstEvalError {
#[track_caller]
fn check_fail(
#[rust_analyzer::rust_fixture] ra_fixture: &str,
- error: impl FnOnce(ConstEvalError) -> bool,
+ error: impl FnOnce(ConstEvalError<'_>) -> bool,
) {
let (db, file_id) = TestDB::with_single_file(ra_fixture);
salsa::attach(&db, || match eval_goal(&db, file_id) {
@@ -100,7 +100,7 @@ fn check_answer(
});
}
-fn pretty_print_err(e: ConstEvalError, db: &TestDB) -> String {
+fn pretty_print_err(e: ConstEvalError<'_>, db: &TestDB) -> String {
let mut err = String::new();
let span_formatter = |file, range| format!("{file:?} {range:?}");
let display_target =
@@ -117,7 +117,7 @@ fn pretty_print_err(e: ConstEvalError, db: &TestDB) -> String {
err
}
-fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const, ConstEvalError> {
+fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const, ConstEvalError<'_>> {
let _tracing = setup_tracing();
let module_id = db.module_for_file(file_id.file_id(db));
let def_map = module_id.def_map(db);
diff --git a/crates/hir-ty/src/consteval_nextsolver.rs b/crates/hir-ty/src/consteval_nextsolver.rs
index 155f1336e4..2509ba2ef2 100644
--- a/crates/hir-ty/src/consteval_nextsolver.rs
+++ b/crates/hir-ty/src/consteval_nextsolver.rs
@@ -178,10 +178,10 @@ pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<
}
}
-pub(crate) fn const_eval_discriminant_variant(
- db: &dyn HirDatabase,
+pub(crate) fn const_eval_discriminant_variant<'db>(
+ db: &'db dyn HirDatabase,
variant_id: EnumVariantId,
-) -> Result<i128, ConstEvalError> {
+) -> Result<i128, ConstEvalError<'db>> {
let interner = DbInterner::new_with(db, None, None);
let def = variant_id.into();
let body = db.body(def);
@@ -220,7 +220,7 @@ pub(crate) fn const_eval_discriminant_variant(
// FIXME: Ideally constants in const eval should have separate body (issue #7434), and this function should
// get an `InferenceResult` instead of an `InferenceContext`. And we should remove `ctx.clone().resolve_all()` here
// and make this function private. See the fixme comment on `InferenceContext::resolve_all`.
-pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'db>) -> Const<'db> {
+pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'_, 'db>) -> Const<'db> {
let interner = DbInterner::new_with(ctx.db, None, None);
let infer = ctx.fixme_resolve_all_clone();
fn has_closure(body: &Body, expr: ExprId) -> bool {
@@ -233,17 +233,11 @@ pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'db>)
}
if has_closure(ctx.body, expr) {
// Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic.
- return unknown_const(infer[expr].clone().to_nextsolver(interner));
+ return unknown_const(infer[expr]);
}
if let Expr::Path(p) = &ctx.body[expr] {
let resolver = &ctx.resolver;
- if let Some(c) = path_to_const(
- ctx.db,
- resolver,
- p,
- || ctx.generics(),
- infer[expr].to_nextsolver(interner),
- ) {
+ if let Some(c) = path_to_const(ctx.db, resolver, p, || ctx.generics(), infer[expr]) {
return c;
}
}
@@ -252,5 +246,5 @@ pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'db>)
{
return result.to_nextsolver(interner);
}
- unknown_const(infer[expr].to_nextsolver(interner))
+ unknown_const(infer[expr])
}
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 71fb3d44fb..82d17cc618 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -32,62 +32,71 @@ use crate::{
pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(crate::infer::infer_query)]
#[salsa::cycle(cycle_result = crate::infer::infer_cycle_result)]
- fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
+ fn infer<'db>(&'db self, def: DefWithBodyId) -> Arc<InferenceResult<'db>>;
// region:mir
#[salsa::invoke(crate::mir::mir_body_query)]
#[salsa::cycle(cycle_result = crate::mir::mir_body_cycle_result)]
- fn mir_body(&self, def: DefWithBodyId) -> Result<Arc<MirBody>, MirLowerError>;
+ fn mir_body<'db>(&'db self, def: DefWithBodyId) -> Result<Arc<MirBody>, MirLowerError<'db>>;
#[salsa::invoke(crate::mir::mir_body_for_closure_query)]
- fn mir_body_for_closure(&self, def: InternedClosureId) -> Result<Arc<MirBody>, MirLowerError>;
+ fn mir_body_for_closure<'db>(
+ &'db self,
+ def: InternedClosureId,
+ ) -> Result<Arc<MirBody>, MirLowerError<'db>>;
#[salsa::invoke(crate::mir::monomorphized_mir_body_query)]
#[salsa::cycle(cycle_result = crate::mir::monomorphized_mir_body_cycle_result)]
- fn monomorphized_mir_body(
- &self,
+ fn monomorphized_mir_body<'db>(
+ &'db self,
def: DefWithBodyId,
subst: Substitution,
- env: Arc<TraitEnvironment<'_>>,
- ) -> Result<Arc<MirBody>, MirLowerError>;
+ env: Arc<TraitEnvironment<'db>>,
+ ) -> Result<Arc<MirBody>, MirLowerError<'db>>;
#[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)]
- fn monomorphized_mir_body_for_closure(
- &self,
+ fn monomorphized_mir_body_for_closure<'db>(
+ &'db self,
def: InternedClosureId,
subst: Substitution,
- env: Arc<TraitEnvironment<'_>>,
- ) -> Result<Arc<MirBody>, MirLowerError>;
+ env: Arc<TraitEnvironment<'db>>,
+ ) -> Result<Arc<MirBody>, MirLowerError<'db>>;
#[salsa::invoke(crate::mir::borrowck_query)]
#[salsa::lru(2024)]
- fn borrowck(&self, def: DefWithBodyId) -> Result<Arc<[BorrowckResult]>, MirLowerError>;
+ fn borrowck<'db>(
+ &'db self,
+ def: DefWithBodyId,
+ ) -> Result<Arc<[BorrowckResult]>, MirLowerError<'db>>;
#[salsa::invoke(crate::consteval::const_eval_query)]
#[salsa::cycle(cycle_result = crate::consteval::const_eval_cycle_result)]
- fn const_eval(
- &self,
+ fn const_eval<'db>(
+ &'db self,
def: GeneralConstId,
subst: Substitution,
- trait_env: Option<Arc<TraitEnvironment<'_>>>,
- ) -> Result<Const, ConstEvalError>;
+ trait_env: Option<Arc<TraitEnvironment<'db>>>,
+ ) -> Result<Const, 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(&self, def: StaticId) -> Result<Const, ConstEvalError>;
+ fn const_eval_static<'db>(&'db self, def: StaticId) -> Result<Const, ConstEvalError<'db>>;
#[salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
#[salsa::cycle(cycle_result = crate::consteval::const_eval_discriminant_cycle_result)]
- fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>;
+ fn const_eval_discriminant<'db>(
+ &'db self,
+ def: EnumVariantId,
+ ) -> Result<i128, ConstEvalError<'db>>;
#[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
- fn lookup_impl_method(
- &self,
- env: Arc<TraitEnvironment<'_>>,
+ fn lookup_impl_method<'db>(
+ &'db self,
+ env: Arc<TraitEnvironment<'db>>,
func: FunctionId,
- fn_subst: Substitution,
- ) -> (FunctionId, Substitution);
+ fn_subst: crate::next_solver::GenericArgs<'db>,
+ ) -> (FunctionId, crate::next_solver::GenericArgs<'db>);
// endregion:mir
@@ -370,6 +379,23 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
&'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>;
}
#[test]
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index d05814e0e7..7b6fb994ec 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -23,6 +23,8 @@ use tracing::debug;
use triomphe::Arc;
use typed_arena::Arena;
+use crate::next_solver::DbInterner;
+use crate::next_solver::mapping::NextSolverToChalk;
use crate::{
Adjust, InferenceResult, Interner, TraitEnvironment, Ty, TyExt, TyKind,
db::HirDatabase,
@@ -74,8 +76,16 @@ impl BodyValidationDiagnostic {
let infer = db.infer(owner);
let body = db.body(owner);
let env = db.trait_environment_for_body(owner);
- let mut validator =
- ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints, env };
+ let interner = DbInterner::new_with(db, Some(env.krate), env.block);
+ let mut validator = ExprValidator {
+ owner,
+ body,
+ infer,
+ diagnostics: Vec::new(),
+ validate_lints,
+ env,
+ interner,
+ };
validator.validate_body(db);
validator.diagnostics
}
@@ -84,10 +94,11 @@ impl BodyValidationDiagnostic {
struct ExprValidator<'db> {
owner: DefWithBodyId,
body: Arc<Body>,
- infer: Arc<InferenceResult>,
+ infer: Arc<InferenceResult<'db>>,
env: Arc<TraitEnvironment<'db>>,
diagnostics: Vec<BodyValidationDiagnostic>,
validate_lints: bool,
+ interner: DbInterner<'db>,
}
impl<'db> ExprValidator<'db> {
@@ -175,7 +186,7 @@ impl<'db> ExprValidator<'db> {
}
if let Some(receiver_ty) = self.infer.type_of_expr_with_adjust(*receiver) {
- checker.prev_receiver_ty = Some(receiver_ty.clone());
+ checker.prev_receiver_ty = Some(receiver_ty.to_chalk(self.interner));
}
}
}
@@ -190,6 +201,7 @@ impl<'db> ExprValidator<'db> {
let Some(scrut_ty) = self.infer.type_of_expr_with_adjust(scrutinee_expr) else {
return;
};
+ let scrut_ty = scrut_ty.to_chalk(self.interner);
if scrut_ty.contains_unknown() {
return;
}
@@ -205,6 +217,7 @@ impl<'db> ExprValidator<'db> {
let Some(pat_ty) = self.infer.type_of_pat_with_adjust(arm.pat) else {
return;
};
+ let pat_ty = pat_ty.to_chalk(self.interner);
if pat_ty.contains_unknown() {
return;
}
@@ -222,7 +235,7 @@ impl<'db> ExprValidator<'db> {
if (pat_ty == scrut_ty
|| scrut_ty
.as_reference()
- .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
+ .map(|(match_expr_ty, ..)| *match_expr_ty == pat_ty)
.unwrap_or(false))
&& types_of_subpatterns_do_match(arm.pat, &self.body, &self.infer)
{
@@ -264,7 +277,7 @@ impl<'db> ExprValidator<'db> {
match_expr,
uncovered_patterns: missing_match_arms(
&cx,
- scrut_ty,
+ &scrut_ty,
witnesses,
m_arms.is_empty(),
self.owner.krate(db),
@@ -298,10 +311,12 @@ impl<'db> ExprValidator<'db> {
);
value_or_partial.is_none_or(|v| !matches!(v, ValueNs::StaticId(_)))
}
- Expr::Field { expr, .. } => match self.infer.type_of_expr[*expr].kind(Interner) {
- TyKind::Adt(adt, ..) if matches!(adt.0, AdtId::UnionId(_)) => false,
- _ => self.is_known_valid_scrutinee(*expr, db),
- },
+ Expr::Field { expr, .. } => {
+ match self.infer.type_of_expr[*expr].to_chalk(self.interner).kind(Interner) {
+ TyKind::Adt(adt, ..) if matches!(adt.0, AdtId::UnionId(_)) => false,
+ _ => self.is_known_valid_scrutinee(*expr, db),
+ }
+ }
Expr::Index { base, .. } => self.is_known_valid_scrutinee(*base, db),
Expr::Cast { expr, .. } => self.is_known_valid_scrutinee(*expr, db),
Expr::Missing => false,
@@ -327,6 +342,7 @@ impl<'db> ExprValidator<'db> {
}
let Some(initializer) = initializer else { continue };
let Some(ty) = self.infer.type_of_expr_with_adjust(initializer) else { continue };
+ let ty = ty.to_chalk(self.interner);
if ty.contains_unknown() {
continue;
}
@@ -357,7 +373,7 @@ impl<'db> ExprValidator<'db> {
pat,
uncovered_patterns: missing_match_arms(
&cx,
- ty,
+ &ty,
witnesses,
false,
self.owner.krate(db),
@@ -542,7 +558,7 @@ impl FilterMapNextChecker {
pub fn record_literal_missing_fields(
db: &dyn HirDatabase,
- infer: &InferenceResult,
+ infer: &InferenceResult<'_>,
id: ExprId,
expr: &Expr,
) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> {
@@ -572,7 +588,7 @@ pub fn record_literal_missing_fields(
pub fn record_pattern_missing_fields(
db: &dyn HirDatabase,
- infer: &InferenceResult,
+ infer: &InferenceResult<'_>,
id: PatId,
pat: &Pat,
) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> {
@@ -600,8 +616,8 @@ pub fn record_pattern_missing_fields(
Some((variant_def, missed_fields, exhaustive))
}
-fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResult) -> bool {
- fn walk(pat: PatId, body: &Body, infer: &InferenceResult, has_type_mismatches: &mut bool) {
+fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResult<'_>) -> bool {
+ fn walk(pat: PatId, body: &Body, infer: &InferenceResult<'_>, has_type_mismatches: &mut bool) {
match infer.type_mismatch_for_pat(pat) {
Some(_) => *has_type_mismatches = true,
None if *has_type_mismatches => (),
diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs
index e803b56a1e..af541ffa34 100644
--- a/crates/hir-ty/src/diagnostics/match_check.rs
+++ b/crates/hir-ty/src/diagnostics/match_check.rs
@@ -20,6 +20,8 @@ use hir_expand::name::Name;
use span::Edition;
use stdx::{always, never};
+use crate::next_solver::DbInterner;
+use crate::next_solver::mapping::NextSolverToChalk;
use crate::{
InferenceResult, Interner, Substitution, Ty, TyExt, TyKind,
db::HirDatabase,
@@ -93,16 +95,21 @@ pub(crate) enum PatKind {
},
}
-pub(crate) struct PatCtxt<'a> {
- db: &'a dyn HirDatabase,
- infer: &'a InferenceResult,
- body: &'a Body,
+pub(crate) struct PatCtxt<'db> {
+ db: &'db dyn HirDatabase,
+ infer: &'db InferenceResult<'db>,
+ body: &'db Body,
pub(crate) errors: Vec<PatternError>,
+ interner: DbInterner<'db>,
}
impl<'a> PatCtxt<'a> {
- pub(crate) fn new(db: &'a dyn HirDatabase, infer: &'a InferenceResult, body: &'a Body) -> Self {
- Self { db, infer, body, errors: Vec::new() }
+ pub(crate) fn new(
+ db: &'a dyn HirDatabase,
+ infer: &'a InferenceResult<'a>,
+ body: &'a Body,
+ ) -> Self {
+ Self { db, infer, body, errors: Vec::new(), interner: DbInterner::new_with(db, None, None) }
}
pub(crate) fn lower_pattern(&mut self, pat: PatId) -> Pat {
@@ -115,14 +122,14 @@ impl<'a> PatCtxt<'a> {
self.infer.pat_adjustments.get(&pat).map(|it| &**it).unwrap_or_default().iter().rev().fold(
unadjusted_pat,
|subpattern, ref_ty| Pat {
- ty: ref_ty.clone(),
+ ty: ref_ty.to_chalk(self.interner).clone(),
kind: Box::new(PatKind::Deref { subpattern }),
},
)
}
fn lower_pattern_unadjusted(&mut self, pat: PatId) -> Pat {
- let mut ty = &self.infer[pat];
+ let mut ty = self.infer[pat].to_chalk(self.interner);
let variant = self.infer.variant_resolution_for_pat(pat);
let kind = match self.body[pat] {
@@ -140,7 +147,7 @@ impl<'a> PatCtxt<'a> {
_ => {
never!("unexpected type for tuple pattern: {:?}", ty);
self.errors.push(PatternError::UnexpectedType);
- return Pat { ty: ty.clone(), kind: PatKind::Wild.into() };
+ return Pat { ty, kind: PatKind::Wild.into() };
}
};
let subpatterns = self.lower_tuple_subpats(args, arity, ellipsis);
@@ -149,10 +156,10 @@ impl<'a> PatCtxt<'a> {
hir_def::hir::Pat::Bind { id, subpat, .. } => {
let bm = self.infer.binding_modes[pat];
- ty = &self.infer[id];
+ ty = self.infer[id].to_chalk(self.interner);
let name = &self.body[id].name;
match (bm, ty.kind(Interner)) {
- (BindingMode::Ref(_), TyKind::Ref(.., rty)) => ty = rty,
+ (BindingMode::Ref(_), TyKind::Ref(.., rty)) => ty = rty.clone(),
(BindingMode::Ref(_), _) => {
never!(
"`ref {}` has wrong type {:?}",
@@ -170,7 +177,7 @@ impl<'a> PatCtxt<'a> {
hir_def::hir::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => {
let expected_len = variant.unwrap().fields(self.db).fields().len();
let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis);
- self.lower_variant_or_leaf(pat, ty, subpatterns)
+ self.lower_variant_or_leaf(pat, &ty, subpatterns)
}
hir_def::hir::Pat::Record { ref args, .. } if variant.is_some() => {
@@ -186,7 +193,7 @@ impl<'a> PatCtxt<'a> {
})
.collect();
match subpatterns {
- Some(subpatterns) => self.lower_variant_or_leaf(pat, ty, subpatterns),
+ Some(subpatterns) => self.lower_variant_or_leaf(pat, &ty, subpatterns),
None => {
self.errors.push(PatternError::MissingField);
PatKind::Wild
@@ -271,12 +278,12 @@ impl<'a> PatCtxt<'a> {
}
fn lower_path(&mut self, pat: PatId, _path: &Path) -> Pat {
- let ty = &self.infer[pat];
+ let ty = self.infer[pat].to_chalk(self.interner);
let pat_from_kind = |kind| Pat { ty: ty.clone(), kind: Box::new(kind) };
match self.infer.variant_resolution_for_pat(pat) {
- Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, ty, Vec::new())),
+ Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, &ty, Vec::new())),
None => {
self.errors.push(PatternError::UnresolvedVariant);
pat_from_kind(PatKind::Wild)
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 3c78f5ef38..31100e17f8 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -14,6 +14,8 @@ use hir_def::{
};
use span::Edition;
+use crate::next_solver::DbInterner;
+use crate::next_solver::mapping::NextSolverToChalk;
use crate::utils::TargetFeatureIsSafeInTarget;
use crate::{
InferenceResult, Interner, TargetFeatures, TyExt, TyKind,
@@ -96,9 +98,9 @@ enum UnsafeDiagnostic {
DeprecatedSafe2024 { node: ExprId, inside_unsafe_block: InsideUnsafeBlock },
}
-pub fn unsafe_operations_for_body(
- db: &dyn HirDatabase,
- infer: &InferenceResult,
+pub fn unsafe_operations_for_body<'db>(
+ db: &'db dyn HirDatabase,
+ infer: &InferenceResult<'db>,
def: DefWithBodyId,
body: &Body,
callback: &mut dyn FnMut(ExprOrPatId),
@@ -115,9 +117,9 @@ pub fn unsafe_operations_for_body(
}
}
-pub fn unsafe_operations(
- db: &dyn HirDatabase,
- infer: &InferenceResult,
+pub fn unsafe_operations<'db>(
+ db: &'db dyn HirDatabase,
+ infer: &InferenceResult<'db>,
def: DefWithBodyId,
body: &Body,
current: ExprId,
@@ -135,7 +137,7 @@ pub fn unsafe_operations(
struct UnsafeVisitor<'db> {
db: &'db dyn HirDatabase,
- infer: &'db InferenceResult,
+ infer: &'db InferenceResult<'db>,
body: &'db Body,
resolver: Resolver<'db>,
def: DefWithBodyId,
@@ -149,12 +151,13 @@ struct UnsafeVisitor<'db> {
/// On some targets (WASM), calling safe functions with `#[target_feature]` is always safe, even when
/// the target feature is not enabled. This flag encodes that.
target_feature_is_safe: TargetFeatureIsSafeInTarget,
+ interner: DbInterner<'db>,
}
impl<'db> UnsafeVisitor<'db> {
fn new(
db: &'db dyn HirDatabase,
- infer: &'db InferenceResult,
+ infer: &'db InferenceResult<'db>,
body: &'db Body,
def: DefWithBodyId,
unsafe_expr_cb: &'db mut dyn FnMut(UnsafeDiagnostic),
@@ -183,6 +186,7 @@ impl<'db> UnsafeVisitor<'db> {
def_target_features,
edition,
target_feature_is_safe,
+ interner: DbInterner::new_with(db, None, None),
}
}
@@ -285,7 +289,7 @@ impl<'db> UnsafeVisitor<'db> {
let inside_assignment = mem::replace(&mut self.inside_assignment, false);
match expr {
&Expr::Call { callee, .. } => {
- let callee = &self.infer[callee];
+ let callee = self.infer[callee].to_chalk(self.interner);
if let Some(func) = callee.as_fn_def(self.db) {
self.check_call(current, func);
}
@@ -338,7 +342,7 @@ impl<'db> UnsafeVisitor<'db> {
}
}
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
- if let TyKind::Raw(..) = &self.infer[*expr].kind(Interner) {
+ if let TyKind::Raw(..) = &self.infer[*expr].to_chalk(self.interner).kind(Interner) {
self.on_unsafe_op(current.into(), UnsafetyReason::RawPtrDeref);
}
}
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index e11ce51cdb..d79069901e 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -1545,14 +1545,17 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
never!("Only `impl Fn` is valid for displaying closures in source code");
}
}
- let chalk_id: chalk_ir::ClosureId<_> = id.into();
match f.closure_style {
ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
ClosureStyle::ClosureWithId => {
- return write!(f, "{{closure#{:?}}}", chalk_id.0.index());
+ return write!(
+ f,
+ "{{closure#{:?}}}",
+ salsa::plumbing::AsId::as_id(&id).index()
+ );
}
ClosureStyle::ClosureWithSubst => {
- write!(f, "{{closure#{:?}}}", chalk_id.0.index())?;
+ write!(f, "{{closure#{:?}}}", salsa::plumbing::AsId::as_id(&id).index())?;
return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
}
_ => (),
@@ -1561,7 +1564,7 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
if let Some(sig) = sig {
let InternedClosure(def, _) = db.lookup_intern_closure(id);
let infer = db.infer(def);
- let (_, kind) = infer.closure_info(&chalk_id);
+ let (_, kind) = infer.closure_info(id);
match f.closure_style {
ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
ClosureStyle::RANotation => write!(f, "|")?,
diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs
index 413f70532a..0618fd17d5 100644
--- a/crates/hir-ty/src/drop.rs
+++ b/crates/hir-ty/src/drop.rs
@@ -8,7 +8,7 @@ use stdx::never;
use triomphe::Arc;
use crate::next_solver::DbInterner;
-use crate::next_solver::mapping::NextSolverToChalk;
+use crate::next_solver::mapping::{ChalkToNextSolver, NextSolverToChalk};
use crate::{
AliasTy, Canonical, CanonicalVarKinds, ConcreteConst, ConstScalar, ConstValue, InEnvironment,
Interner, ProjectionTy, TraitEnvironment, Ty, TyBuilder, TyKind, db::HirDatabase,
@@ -120,13 +120,20 @@ pub(crate) fn has_drop_glue(
}
TyKind::Slice(ty) => db.has_drop_glue(ty.clone(), env),
TyKind::Closure(closure_id, subst) => {
- let owner = db.lookup_intern_closure((*closure_id).into()).0;
+ let closure_id = (*closure_id).into();
+ let owner = db.lookup_intern_closure(closure_id).0;
let infer = db.infer(owner);
let (captures, _) = infer.closure_info(closure_id);
let env = db.trait_environment_for_body(owner);
+ let interner = DbInterner::conjure();
captures
.iter()
- .map(|capture| db.has_drop_glue(capture.ty(db, subst), env.clone()))
+ .map(|capture| {
+ db.has_drop_glue(
+ capture.ty(db, subst.to_nextsolver(interner)).to_chalk(interner),
+ env.clone(),
+ )
+ })
.max()
.unwrap_or(DropGlue::None)
}
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 0282b7a936..72498681ac 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -28,19 +28,11 @@ pub(crate) mod unify;
use std::{cell::OnceCell, convert::identity, iter, ops::Index};
use base_db::Crate;
-use chalk_ir::{
- DebruijnIndex, Mutability, Safety, Scalar, TyKind, TypeFlags, Variance,
- cast::Cast,
- fold::TypeFoldable,
- interner::HasInterner,
- visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
-};
use either::Either;
use hir_def::{
AdtId, AssocItemId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId, GenericParamId,
ImplId, ItemContainerId, LocalFieldId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId,
VariantId,
- builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
expr_store::{Body, ExpressionStore, HygieneId, path::Path},
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
lang_item::{LangItem, LangItemTarget, lang_item},
@@ -53,18 +45,19 @@ use hir_expand::{mod_path::ModPath, name::Name};
use indexmap::IndexSet;
use intern::sym;
use la_arena::{ArenaMap, Entry};
+use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
-use rustc_type_ir::inherent::Ty as _;
-use stdx::{always, never};
+use rustc_type_ir::{
+ AliasTyKind, Flags, TypeFlags, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+ inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _},
+};
+use stdx::never;
use triomphe::Arc;
use crate::{
- AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, ImplTraitId, ImplTraitIdx,
- IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, ParamLoweringMode,
- PathLoweringDiagnostic, ProjectionTy, Substitution, TargetFeatures, TraitEnvironment, Ty,
- TyBuilder, TyExt,
- db::{HirDatabase, InternedClosureId},
- fold_tys,
+ ImplTraitId, IncorrectGenericsLenKind, Interner, PathLoweringDiagnostic, TargetFeatures,
+ TraitEnvironment,
+ db::{HirDatabase, InternedClosureId, InternedOpaqueTyId},
generics::Generics,
infer::{
coerce::{CoerceMany, DynamicCoerceMany},
@@ -72,16 +65,22 @@ use crate::{
expr::ExprIsRead,
unify::InferenceTable,
},
- lower::{ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic},
+ lower::diagnostics::TyLoweringDiagnostic,
+ lower_nextsolver::{ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind},
mir::MirSpan,
next_solver::{
- self, DbInterner,
- infer::{DefineOpaqueTypes, traits::ObligationCause},
+ AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region, Ty, TyKind,
+ Tys,
+ abi::Safety,
+ fold::fold_tys,
+ infer::{
+ DefineOpaqueTypes,
+ traits::{Obligation, ObligationCause},
+ },
mapping::{ChalkToNextSolver, NextSolverToChalk},
},
- static_lifetime, to_assoc_type_id,
traits::FnTrait,
- utils::{TargetFeatureIsSafeInTarget, UnevaluatedConstEvaluatorFolder},
+ utils::TargetFeatureIsSafeInTarget,
};
// This lint has a false positive here. See the link below for details.
@@ -96,7 +95,7 @@ use cast::{CastCheck, CastError};
pub(crate) use closure::analysis::{CaptureKind, CapturedItem, CapturedItemWithoutTy};
/// The entry point of type inference.
-pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
+pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult<'_>> {
let _p = tracing::info_span!("infer_query").entered();
let resolver = def.resolver(db);
let body = db.body(def);
@@ -109,30 +108,28 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
DefWithBodyId::ConstId(c) => ctx.collect_const(c, &db.const_signature(c)),
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_signature(s)),
DefWithBodyId::VariantId(v) => {
- ctx.return_ty = TyBuilder::builtin(
- match db.enum_signature(v.lookup(db).parent).variant_body_type() {
- hir_def::layout::IntegerType::Pointer(signed) => match signed {
- true => BuiltinType::Int(BuiltinInt::Isize),
- false => BuiltinType::Uint(BuiltinUint::Usize),
+ ctx.return_ty = match db.enum_signature(v.lookup(db).parent).variant_body_type() {
+ hir_def::layout::IntegerType::Pointer(signed) => match signed {
+ true => ctx.types.isize,
+ false => ctx.types.usize,
+ },
+ hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
+ true => match size {
+ Integer::I8 => ctx.types.i8,
+ Integer::I16 => ctx.types.i16,
+ Integer::I32 => ctx.types.i32,
+ Integer::I64 => ctx.types.i64,
+ Integer::I128 => ctx.types.i128,
},
- hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
- true => BuiltinType::Int(match size {
- Integer::I8 => BuiltinInt::I8,
- Integer::I16 => BuiltinInt::I16,
- Integer::I32 => BuiltinInt::I32,
- Integer::I64 => BuiltinInt::I64,
- Integer::I128 => BuiltinInt::I128,
- }),
- false => BuiltinType::Uint(match size {
- Integer::I8 => BuiltinUint::U8,
- Integer::I16 => BuiltinUint::U16,
- Integer::I32 => BuiltinUint::U32,
- Integer::I64 => BuiltinUint::U64,
- Integer::I128 => BuiltinUint::U128,
- }),
+ false => match size {
+ Integer::I8 => ctx.types.u8,
+ Integer::I16 => ctx.types.u16,
+ Integer::I32 => ctx.types.u32,
+ Integer::I64 => ctx.types.u64,
+ Integer::I128 => ctx.types.u128,
},
},
- );
+ };
}
}
@@ -159,8 +156,14 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
Arc::new(ctx.resolve_all())
}
-pub(crate) fn infer_cycle_result(_: &dyn HirDatabase, _: DefWithBodyId) -> Arc<InferenceResult> {
- Arc::new(InferenceResult { has_errors: true, ..Default::default() })
+pub(crate) fn infer_cycle_result(
+ db: &dyn HirDatabase,
+ _: DefWithBodyId,
+) -> Arc<InferenceResult<'_>> {
+ Arc::new(InferenceResult {
+ has_errors: true,
+ ..InferenceResult::new(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed))
+ })
}
/// Fully normalize all the types found within `ty` in context of `owner` body definition.
@@ -168,20 +171,24 @@ pub(crate) fn infer_cycle_result(_: &dyn HirDatabase, _: DefWithBodyId) -> Arc<I
/// This is appropriate to use only after type-check: it assumes
/// that normalization will succeed, for example.
#[tracing::instrument(level = "debug", skip(db))]
-pub(crate) fn normalize(db: &dyn HirDatabase, trait_env: Arc<TraitEnvironment<'_>>, ty: Ty) -> Ty {
+pub(crate) fn normalize(
+ db: &dyn HirDatabase,
+ trait_env: Arc<TraitEnvironment<'_>>,
+ ty: crate::Ty,
+) -> crate::Ty {
// FIXME: TypeFlags::HAS_CT_PROJECTION is not implemented in chalk, so TypeFlags::HAS_PROJECTION only
// works for the type case, so we check array unconditionally. Remove the array part
// when the bug in chalk becomes fixed.
- if !ty.data(Interner).flags.intersects(TypeFlags::HAS_PROJECTION)
- && !matches!(ty.kind(Interner), TyKind::Array(..))
+ if !ty.data(Interner).flags.intersects(crate::TypeFlags::HAS_PROJECTION)
+ && !matches!(ty.kind(Interner), crate::TyKind::Array(..))
{
return ty;
}
let mut table = unify::InferenceTable::new(db, trait_env);
- let ty_with_vars = table.normalize_associated_types_in(ty);
+ let ty_with_vars = table.normalize_associated_types_in(ty.to_nextsolver(table.interner()));
table.select_obligations_where_possible();
- table.resolve_completely(ty_with_vars)
+ table.resolve_completely(ty_with_vars).to_chalk(table.interner())
}
/// Binding modes inferred for patterns.
@@ -203,14 +210,6 @@ impl BindingMode {
}
}
-// FIXME: Remove this `InferOk`, switch all code to the second one, that uses `Obligation` instead of `Goal`.
-#[derive(Debug)]
-pub(crate) struct InferOk<'db, T> {
- #[allow(dead_code)]
- value: T,
- goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>,
-}
-
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum InferenceTyDiagnosticSource {
/// Diagnostics that come from types in the body.
@@ -219,12 +218,8 @@ pub enum InferenceTyDiagnosticSource {
Signature,
}
-#[derive(Debug)]
-pub(crate) struct TypeError;
-pub(crate) type InferResult<'db, T> = Result<InferOk<'db, T>, TypeError>;
-
#[derive(Debug, PartialEq, Eq, Clone)]
-pub enum InferenceDiagnostic {
+pub enum InferenceDiagnostic<'db> {
NoSuchField {
field: ExprOrPatId,
private: Option<LocalFieldId>,
@@ -240,16 +235,16 @@ pub enum InferenceDiagnostic {
},
UnresolvedField {
expr: ExprId,
- receiver: Ty,
+ receiver: Ty<'db>,
name: Name,
method_with_same_name_exists: bool,
},
UnresolvedMethodCall {
expr: ExprId,
- receiver: Ty,
+ receiver: Ty<'db>,
name: Name,
/// Contains the type the field resolves to
- field_with_same_name: Option<Ty>,
+ field_with_same_name: Option<Ty<'db>>,
assoc_func_with_same_name: Option<FunctionId>,
},
UnresolvedAssocItem {
@@ -276,21 +271,21 @@ pub enum InferenceDiagnostic {
},
ExpectedFunction {
call_expr: ExprId,
- found: Ty,
+ found: Ty<'db>,
},
TypedHole {
expr: ExprId,
- expected: Ty,
+ expected: Ty<'db>,
},
CastToUnsized {
expr: ExprId,
- cast_ty: Ty,
+ cast_ty: Ty<'db>,
},
InvalidCast {
expr: ExprId,
error: CastError,
- expr_ty: Ty,
- cast_ty: Ty,
+ expr_ty: Ty<'db>,
+ cast_ty: Ty<'db>,
},
TyDiagnostic {
source: InferenceTyDiagnosticSource,
@@ -318,29 +313,11 @@ pub enum InferenceDiagnostic {
/// A mismatch between an expected and an inferred type.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct TypeMismatch {
- pub expected: Ty,
- pub actual: Ty,
+pub struct TypeMismatch<'db> {
+ pub expected: Ty<'db>,
+ pub actual: Ty<'db>,
}
-#[derive(Clone, PartialEq, Eq, Debug)]
-struct InternedStandardTypes {
- unknown: Ty,
- bool_: Ty,
- unit: Ty,
- never: Ty,
-}
-
-impl Default for InternedStandardTypes {
- fn default() -> Self {
- InternedStandardTypes {
- unknown: TyKind::Error.intern(Interner),
- bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
- unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
- never: TyKind::Never.intern(Interner),
- }
- }
-}
/// Represents coercing a value to a different type of value.
///
/// We transform values by following a number of `Adjust` steps in order.
@@ -382,14 +359,14 @@ impl Default for InternedStandardTypes {
/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct Adjustment {
- pub kind: Adjust,
- pub target: Ty,
+pub struct Adjustment<'db> {
+ pub kind: Adjust<'db>,
+ pub target: Ty<'db>,
}
-impl Adjustment {
- pub fn borrow(m: Mutability, ty: Ty, lt: Lifetime) -> Self {
- let ty = TyKind::Ref(m, lt.clone(), ty).intern(Interner);
+impl<'db> Adjustment<'db> {
+ pub fn borrow(interner: DbInterner<'db>, m: Mutability, ty: Ty<'db>, lt: Region<'db>) -> Self {
+ let ty = Ty::new_ref(interner, lt, ty, m);
Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(lt, m)), target: ty }
}
}
@@ -415,13 +392,13 @@ pub(crate) enum AllowTwoPhase {
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub enum Adjust {
+pub enum Adjust<'db> {
/// Go from ! to any type.
NeverToAny,
/// Dereference once, producing a place.
Deref(Option<OverloadedDeref>),
/// Take the address and produce either a `&` or `*` pointer.
- Borrow(AutoBorrow),
+ Borrow(AutoBorrow<'db>),
Pointer(PointerCast),
}
@@ -433,14 +410,14 @@ pub enum Adjust {
pub struct OverloadedDeref(pub Option<Mutability>);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub enum AutoBorrow {
+pub enum AutoBorrow<'db> {
/// Converts from T to &T.
- Ref(Lifetime, Mutability),
+ Ref(Region<'db>, Mutability),
/// Converts from T to *T.
RawPtr(Mutability),
}
-impl AutoBorrow {
+impl<'db> AutoBorrow<'db> {
fn mutability(&self) -> Mutability {
let (AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m)) = self;
*m
@@ -484,41 +461,41 @@ pub enum PointerCast {
/// When you add a field that stores types (including `Substitution` and the like), don't forget
/// `resolve_completely()`'ing them in `InferenceContext::resolve_all()`. Inference variables must
/// not appear in the final inference result.
-#[derive(Clone, PartialEq, Eq, Debug, Default)]
-pub struct InferenceResult {
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct InferenceResult<'db> {
/// For each method call expr, records the function it resolves to.
- method_resolutions: FxHashMap<ExprId, (FunctionId, Substitution)>,
+ method_resolutions: FxHashMap<ExprId, (FunctionId, GenericArgs<'db>)>,
/// For each field access expr, records the field it resolves to.
field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>,
/// For each struct literal or pattern, records the variant it resolves to.
variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
/// For each associated item record what it resolves to
- assoc_resolutions: FxHashMap<ExprOrPatId, (AssocItemId, Substitution)>,
+ assoc_resolutions: FxHashMap<ExprOrPatId, (AssocItemId, GenericArgs<'db>)>,
/// Whenever a tuple field expression access a tuple field, we allocate a tuple id in
/// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of
/// that which allows us to resolve a [`TupleFieldId`]s type.
- tuple_field_access_types: FxHashMap<TupleId, Substitution>,
+ tuple_field_access_types: FxHashMap<TupleId, Tys<'db>>,
/// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
- diagnostics: Vec<InferenceDiagnostic>,
- pub(crate) type_of_expr: ArenaMap<ExprId, Ty>,
+ diagnostics: Vec<InferenceDiagnostic<'db>>,
+ pub(crate) type_of_expr: ArenaMap<ExprId, Ty<'db>>,
/// For each pattern record the type it resolves to.
///
/// **Note**: When a pattern type is resolved it may still contain
/// unresolved or missing subpatterns or subpatterns of mismatched types.
- pub(crate) type_of_pat: ArenaMap<PatId, Ty>,
- pub(crate) type_of_binding: ArenaMap<BindingId, Ty>,
- pub(crate) type_of_rpit: ArenaMap<ImplTraitIdx, Ty>,
- type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
+ pub(crate) type_of_pat: ArenaMap<PatId, Ty<'db>>,
+ pub(crate) type_of_binding: ArenaMap<BindingId, Ty<'db>>,
+ pub(crate) type_of_rpit: ArenaMap<ImplTraitIdx<'db>, Ty<'db>>,
+ type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch<'db>>,
/// Whether there are any type-mismatching errors in the result.
// FIXME: This isn't as useful as initially thought due to us falling back placeholders to
// `TyKind::Error`.
// Which will then mark this field.
pub(crate) has_errors: bool,
- /// Interned common types to return references to.
- // FIXME: Move this into `InferenceContext`
- standard_types: InternedStandardTypes,
+ /// Interned `Error` type to return references to.
+ // FIXME: Remove this.
+ error_ty: Ty<'db>,
/// Stores the types which were implicitly dereferenced in pattern binding modes.
- pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
+ pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty<'db>>>,
/// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
///
/// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an
@@ -533,16 +510,40 @@ pub struct InferenceResult {
/// ```
/// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.
pub(crate) binding_modes: ArenaMap<PatId, BindingMode>,
- pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,
- pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>,
+ pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment<'db>]>>,
+ pub(crate) closure_info: FxHashMap<InternedClosureId, (Vec<CapturedItem<'db>>, FnTrait)>,
// FIXME: remove this field
pub mutated_bindings_in_closure: FxHashSet<BindingId>,
pub(crate) coercion_casts: FxHashSet<ExprId>,
}
-impl InferenceResult {
- pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, Substitution)> {
- self.method_resolutions.get(&expr).cloned()
+impl<'db> InferenceResult<'db> {
+ fn new(error_ty: Ty<'db>) -> Self {
+ Self {
+ method_resolutions: Default::default(),
+ field_resolutions: Default::default(),
+ variant_resolutions: Default::default(),
+ assoc_resolutions: Default::default(),
+ tuple_field_access_types: Default::default(),
+ diagnostics: Default::default(),
+ type_of_expr: Default::default(),
+ type_of_pat: Default::default(),
+ type_of_binding: Default::default(),
+ type_of_rpit: Default::default(),
+ type_mismatches: Default::default(),
+ has_errors: Default::default(),
+ error_ty,
+ pat_adjustments: Default::default(),
+ binding_modes: Default::default(),
+ expr_adjustments: Default::default(),
+ closure_info: Default::default(),
+ mutated_bindings_in_closure: Default::default(),
+ coercion_casts: Default::default(),
+ }
+ }
+
+ pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {
+ self.method_resolutions.get(&expr).copied()
}
pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> {
self.field_resolutions.get(&expr).copied()
@@ -559,46 +560,49 @@ impl InferenceResult {
ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),
}
}
- pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<(AssocItemId, Substitution)> {
- self.assoc_resolutions.get(&id.into()).cloned()
+ pub fn assoc_resolutions_for_expr(
+ &self,
+ id: ExprId,
+ ) -> Option<(AssocItemId, GenericArgs<'db>)> {
+ self.assoc_resolutions.get(&id.into()).copied()
}
- pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<(AssocItemId, Substitution)> {
- self.assoc_resolutions.get(&id.into()).cloned()
+ pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<(AssocItemId, GenericArgs<'db>)> {
+ self.assoc_resolutions.get(&id.into()).copied()
}
pub fn assoc_resolutions_for_expr_or_pat(
&self,
id: ExprOrPatId,
- ) -> Option<(AssocItemId, Substitution)> {
+ ) -> Option<(AssocItemId, GenericArgs<'db>)> {
match id {
ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id),
ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),
}
}
- pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
+ pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch<'db>> {
self.type_mismatches.get(&expr.into())
}
- pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> {
+ pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch<'db>> {
self.type_mismatches.get(&pat.into())
}
- pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch)> {
+ pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch<'db>)> {
self.type_mismatches.iter().map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch))
}
- pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> {
+ pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch<'db>)> {
self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat {
ExprOrPatId::ExprId(expr) => Some((expr, mismatch)),
_ => None,
})
}
- pub fn closure_info(&self, closure: &ClosureId) -> &(Vec<CapturedItem>, FnTrait) {
- self.closure_info.get(closure).unwrap()
+ pub fn closure_info(&self, closure: InternedClosureId) -> &(Vec<CapturedItem<'db>>, FnTrait) {
+ self.closure_info.get(&closure).unwrap()
}
- pub fn type_of_expr_or_pat(&self, id: ExprOrPatId) -> Option<&Ty> {
+ pub fn type_of_expr_or_pat(&self, id: ExprOrPatId) -> Option<Ty<'db>> {
match id {
- ExprOrPatId::ExprId(id) => self.type_of_expr.get(id),
- ExprOrPatId::PatId(id) => self.type_of_pat.get(id),
+ ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).copied(),
+ ExprOrPatId::PatId(id) => self.type_of_pat.get(id).copied(),
}
}
- pub fn type_of_expr_with_adjust(&self, id: ExprId) -> Option<&Ty> {
+ pub fn type_of_expr_with_adjust(&self, id: ExprId) -> Option<Ty<'db>> {
match self.expr_adjustments.get(&id).and_then(|adjustments| {
adjustments
.iter()
@@ -614,33 +618,33 @@ impl InferenceResult {
})
.next_back()
}) {
- Some(adjustment) => Some(&adjustment.target),
- None => self.type_of_expr.get(id),
+ Some(adjustment) => Some(adjustment.target),
+ None => self.type_of_expr.get(id).copied(),
}
}
- pub fn type_of_pat_with_adjust(&self, id: PatId) -> Option<&Ty> {
+ pub fn type_of_pat_with_adjust(&self, id: PatId) -> Option<Ty<'db>> {
match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {
- adjusted @ Some(_) => adjusted,
- None => self.type_of_pat.get(id),
+ Some(adjusted) => Some(*adjusted),
+ None => self.type_of_pat.get(id).copied(),
}
}
pub fn is_erroneous(&self) -> bool {
self.has_errors && self.type_of_expr.iter().count() == 0
}
- pub fn diagnostics(&self) -> &[InferenceDiagnostic] {
+ pub fn diagnostics(&self) -> &[InferenceDiagnostic<'db>] {
&self.diagnostics
}
- pub fn tuple_field_access_type(&self, id: TupleId) -> &Substitution {
- &self.tuple_field_access_types[&id]
+ pub fn tuple_field_access_type(&self, id: TupleId) -> Tys<'db> {
+ self.tuple_field_access_types[&id]
}
- pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty]> {
+ pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty<'db>]> {
self.pat_adjustments.get(&id).map(|it| &**it)
}
- pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> {
+ pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment<'db>]> {
self.expr_adjustments.get(&id).map(|it| &**it)
}
@@ -649,83 +653,138 @@ impl InferenceResult {
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn expression_types(&self) -> impl Iterator<Item = (ExprId, &Ty)> {
- self.type_of_expr.iter()
+ pub fn expression_types(&self) -> impl Iterator<Item = (ExprId, Ty<'db>)> {
+ self.type_of_expr.iter().map(|(k, v)| (k, *v))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn pattern_types(&self) -> impl Iterator<Item = (PatId, &Ty)> {
- self.type_of_pat.iter()
+ pub fn pattern_types(&self) -> impl Iterator<Item = (PatId, Ty<'db>)> {
+ self.type_of_pat.iter().map(|(k, v)| (k, *v))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn binding_types(&self) -> impl Iterator<Item = (BindingId, &Ty)> {
- self.type_of_binding.iter()
+ pub fn binding_types(&self) -> impl Iterator<Item = (BindingId, Ty<'db>)> {
+ self.type_of_binding.iter().map(|(k, v)| (k, *v))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn return_position_impl_trait_types(&self) -> impl Iterator<Item = (ImplTraitIdx, &Ty)> {
- self.type_of_rpit.iter()
+ pub fn return_position_impl_trait_types(
+ &self,
+ ) -> impl Iterator<Item = (ImplTraitIdx<'db>, Ty<'db>)> {
+ self.type_of_rpit.iter().map(|(k, v)| (k, *v))
}
}
-impl Index<ExprId> for InferenceResult {
- type Output = Ty;
+impl<'db> Index<ExprId> for InferenceResult<'db> {
+ type Output = Ty<'db>;
- fn index(&self, expr: ExprId) -> &Ty {
- self.type_of_expr.get(expr).unwrap_or(&self.standard_types.unknown)
+ fn index(&self, expr: ExprId) -> &Ty<'db> {
+ self.type_of_expr.get(expr).unwrap_or(&self.error_ty)
}
}
-impl Index<PatId> for InferenceResult {
- type Output = Ty;
+impl<'db> Index<PatId> for InferenceResult<'db> {
+ type Output = Ty<'db>;
- fn index(&self, pat: PatId) -> &Ty {
- self.type_of_pat.get(pat).unwrap_or(&self.standard_types.unknown)
+ fn index(&self, pat: PatId) -> &Ty<'db> {
+ self.type_of_pat.get(pat).unwrap_or(&self.error_ty)
}
}
-impl Index<ExprOrPatId> for InferenceResult {
- type Output = Ty;
+impl<'db> Index<ExprOrPatId> for InferenceResult<'db> {
+ type Output = Ty<'db>;
- fn index(&self, id: ExprOrPatId) -> &Ty {
- self.type_of_expr_or_pat(id).unwrap_or(&self.standard_types.unknown)
+ fn index(&self, id: ExprOrPatId) -> &Ty<'db> {
+ match id {
+ ExprOrPatId::ExprId(id) => &self[id],
+ ExprOrPatId::PatId(id) => &self[id],
+ }
}
}
-impl Index<BindingId> for InferenceResult {
- type Output = Ty;
+impl<'db> Index<BindingId> for InferenceResult<'db> {
+ type Output = Ty<'db>;
- fn index(&self, b: BindingId) -> &Ty {
- self.type_of_binding.get(b).unwrap_or(&self.standard_types.unknown)
+ fn index(&self, b: BindingId) -> &Ty<'db> {
+ self.type_of_binding.get(b).unwrap_or(&self.error_ty)
}
}
#[derive(Debug, Clone)]
-struct InternedStandardTypesNextSolver<'db> {
- unit: crate::next_solver::Ty<'db>,
- never: crate::next_solver::Ty<'db>,
- i32: crate::next_solver::Ty<'db>,
- f64: crate::next_solver::Ty<'db>,
+struct InternedStandardTypes<'db> {
+ unit: Ty<'db>,
+ never: Ty<'db>,
+ char: Ty<'db>,
+ bool: Ty<'db>,
+ i8: Ty<'db>,
+ i16: Ty<'db>,
+ i32: Ty<'db>,
+ i64: Ty<'db>,
+ i128: Ty<'db>,
+ isize: Ty<'db>,
+ u8: Ty<'db>,
+ u16: Ty<'db>,
+ u32: Ty<'db>,
+ u64: Ty<'db>,
+ u128: Ty<'db>,
+ usize: Ty<'db>,
+ f16: Ty<'db>,
+ f32: Ty<'db>,
+ f64: Ty<'db>,
+ f128: Ty<'db>,
+ static_str_ref: Ty<'db>,
+ error: Ty<'db>,
+
+ re_static: Region<'db>,
+ re_error: Region<'db>,
+
+ empty_args: GenericArgs<'db>,
+ empty_tys: Tys<'db>,
}
-impl<'db> InternedStandardTypesNextSolver<'db> {
+impl<'db> InternedStandardTypes<'db> {
fn new(interner: DbInterner<'db>) -> Self {
+ let str = Ty::new(interner, rustc_type_ir::TyKind::Str);
+ let re_static = Region::new_static(interner);
Self {
- unit: crate::next_solver::Ty::new_unit(interner),
- never: crate::next_solver::Ty::new(interner, crate::next_solver::TyKind::Never),
- i32: crate::next_solver::Ty::new_int(interner, rustc_type_ir::IntTy::I32),
- f64: crate::next_solver::Ty::new_float(interner, rustc_type_ir::FloatTy::F64),
+ unit: Ty::new_unit(interner),
+ never: Ty::new(interner, TyKind::Never),
+ char: Ty::new(interner, TyKind::Char),
+ bool: Ty::new(interner, TyKind::Bool),
+ i8: Ty::new_int(interner, rustc_type_ir::IntTy::I8),
+ i16: Ty::new_int(interner, rustc_type_ir::IntTy::I16),
+ i32: Ty::new_int(interner, rustc_type_ir::IntTy::I32),
+ i64: Ty::new_int(interner, rustc_type_ir::IntTy::I64),
+ i128: Ty::new_int(interner, rustc_type_ir::IntTy::I128),
+ isize: Ty::new_int(interner, rustc_type_ir::IntTy::Isize),
+ u8: Ty::new_uint(interner, rustc_type_ir::UintTy::U8),
+ u16: Ty::new_uint(interner, rustc_type_ir::UintTy::U16),
+ u32: Ty::new_uint(interner, rustc_type_ir::UintTy::U32),
+ u64: Ty::new_uint(interner, rustc_type_ir::UintTy::U64),
+ u128: Ty::new_uint(interner, rustc_type_ir::UintTy::U128),
+ usize: Ty::new_uint(interner, rustc_type_ir::UintTy::Usize),
+ f16: Ty::new_float(interner, rustc_type_ir::FloatTy::F16),
+ f32: Ty::new_float(interner, rustc_type_ir::FloatTy::F32),
+ f64: Ty::new_float(interner, rustc_type_ir::FloatTy::F64),
+ f128: Ty::new_float(interner, rustc_type_ir::FloatTy::F128),
+ static_str_ref: Ty::new_ref(interner, re_static, str, Mutability::Not),
+ error: Ty::new_error(interner, ErrorGuaranteed),
+
+ re_static,
+ re_error: Region::error(interner),
+
+ empty_args: GenericArgs::new_from_iter(interner, []),
+ empty_tys: Tys::new_from_iter(interner, []),
}
}
}
/// The inference context contains all information needed during type inference.
#[derive(Clone, Debug)]
-pub(crate) struct InferenceContext<'db> {
+pub(crate) struct InferenceContext<'body, 'db> {
pub(crate) db: &'db dyn HirDatabase,
pub(crate) owner: DefWithBodyId,
- pub(crate) body: &'db Body,
+ pub(crate) body: &'body Body,
/// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext
/// and resolve the path via its methods. This will ensure proper error reporting.
pub(crate) resolver: Resolver<'db>,
@@ -735,32 +794,32 @@ pub(crate) struct InferenceContext<'db> {
table: unify::InferenceTable<'db>,
/// The traits in scope, disregarding block modules. This is used for caching purposes.
traits_in_scope: FxHashSet<TraitId>,
- pub(crate) result: InferenceResult,
+ pub(crate) result: InferenceResult<'db>,
tuple_field_accesses_rev:
- IndexSet<Substitution, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,
+ IndexSet<Tys<'db>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,
/// The return type of the function being inferred, the closure or async block if we're
/// currently within one.
///
/// We might consider using a nested inference context for checking
/// closures so we can swap all shared things out at once.
- return_ty: Ty,
+ return_ty: Ty<'db>,
/// If `Some`, this stores coercion information for returned
/// expressions. If `None`, this is in a context where return is
/// inappropriate, such as a const expression.
return_coercion: Option<DynamicCoerceMany<'db>>,
/// The resume type and the yield type, respectively, of the coroutine being inferred.
- resume_yield_tys: Option<(Ty, Ty)>,
+ resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>,
diverges: Diverges,
breakables: Vec<BreakableContext<'db>>,
- types: InternedStandardTypesNextSolver<'db>,
+ types: InternedStandardTypes<'db>,
/// Whether we are inside the pattern of a destructuring assignment.
inside_assignment: bool,
- deferred_cast_checks: Vec<CastCheck>,
+ deferred_cast_checks: Vec<CastCheck<'db>>,
// fields related to closure capture
- current_captures: Vec<CapturedItemWithoutTy>,
+ current_captures: Vec<CapturedItemWithoutTy<'db>>,
/// A stack that has an entry for each projection in the current capture.
///
/// For example, in `a.b.c`, we capture the spans of `a`, `a.b`, and `a.b.c`.
@@ -771,9 +830,9 @@ pub(crate) struct InferenceContext<'db> {
/// Stores the list of closure ids that need to be analyzed before this closure. See the
/// comment on `InferenceContext::sort_closures`
closure_dependencies: FxHashMap<InternedClosureId, Vec<InternedClosureId>>,
- deferred_closures: FxHashMap<InternedClosureId, Vec<(Ty, Ty, Vec<Ty>, ExprId)>>,
+ deferred_closures: FxHashMap<InternedClosureId, Vec<(Ty<'db>, Ty<'db>, Vec<Ty<'db>>, ExprId)>>,
- diagnostics: Diagnostics,
+ diagnostics: Diagnostics<'db>,
}
#[derive(Clone, Debug)]
@@ -820,28 +879,29 @@ fn find_continuable<'a, 'db>(
}
}
-enum ImplTraitReplacingMode {
- ReturnPosition(FxHashSet<Ty>),
+enum ImplTraitReplacingMode<'db> {
+ ReturnPosition(FxHashSet<Ty<'db>>),
TypeAlias,
}
-impl<'db> InferenceContext<'db> {
+impl<'body, 'db> InferenceContext<'body, 'db> {
fn new(
db: &'db dyn HirDatabase,
owner: DefWithBodyId,
- body: &'db Body,
+ body: &'body Body,
resolver: Resolver<'db>,
) -> Self {
let trait_env = db.trait_environment_for_body(owner);
let table = unify::InferenceTable::new(db, trait_env);
+ let types = InternedStandardTypes::new(table.interner());
InferenceContext {
- types: InternedStandardTypesNextSolver::new(table.interner),
+ result: InferenceResult::new(types.error),
+ return_ty: types.error, // set in collect_* calls
+ types,
target_features: OnceCell::new(),
generics: OnceCell::new(),
- result: InferenceResult::default(),
table,
tuple_field_accesses_rev: Default::default(),
- return_ty: TyKind::Error.intern(Interner), // set in collect_* calls
resume_yield_tys: None,
return_coercion: None,
db,
@@ -904,7 +964,7 @@ impl<'db> InferenceContext<'db> {
/// Clones `self` and calls `resolve_all()` on it.
// FIXME: Remove this.
- pub(crate) fn fixme_resolve_all_clone(&self) -> InferenceResult {
+ pub(crate) fn fixme_resolve_all_clone(&self) -> InferenceResult<'db> {
let mut ctx = self.clone();
ctx.type_inference_fallback();
@@ -928,7 +988,7 @@ impl<'db> InferenceContext<'db> {
// `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you
// used this function for another workaround, mention it here. If you really need this function and believe that
// there is no problem in it being `pub(crate)`, remove this comment.
- pub(crate) fn resolve_all(self) -> InferenceResult {
+ pub(crate) fn resolve_all(self) -> InferenceResult<'db> {
let InferenceContext {
mut table, mut result, tuple_field_accesses_rev, diagnostics, ..
} = self;
@@ -946,7 +1006,7 @@ impl<'db> InferenceContext<'db> {
type_of_rpit,
type_mismatches,
has_errors,
- standard_types: _,
+ error_ty: _,
pat_adjustments,
binding_modes: _,
expr_adjustments,
@@ -961,39 +1021,32 @@ impl<'db> InferenceContext<'db> {
} = &mut result;
for ty in type_of_expr.values_mut() {
- *ty = table.resolve_completely(ty.clone());
- *has_errors = *has_errors || ty.contains_unknown();
+ *ty = table.resolve_completely(*ty);
+ *has_errors = *has_errors || ty.references_non_lt_error();
}
type_of_expr.shrink_to_fit();
for ty in type_of_pat.values_mut() {
- *ty = table.resolve_completely(ty.clone());
- *has_errors = *has_errors || ty.contains_unknown();
+ *ty = table.resolve_completely(*ty);
+ *has_errors = *has_errors || ty.references_non_lt_error();
}
type_of_pat.shrink_to_fit();
for ty in type_of_binding.values_mut() {
- *ty = table.resolve_completely(ty.clone());
- *has_errors = *has_errors || ty.contains_unknown();
+ *ty = table.resolve_completely(*ty);
+ *has_errors = *has_errors || ty.references_non_lt_error();
}
type_of_binding.shrink_to_fit();
for ty in type_of_rpit.values_mut() {
- *ty = table.resolve_completely(ty.clone());
- *has_errors = *has_errors || ty.contains_unknown();
+ *ty = table.resolve_completely(*ty);
+ *has_errors = *has_errors || ty.references_non_lt_error();
}
type_of_rpit.shrink_to_fit();
*has_errors |= !type_mismatches.is_empty();
- type_mismatches.retain(|_, mismatch| {
- mismatch.expected = table.resolve_completely(mismatch.expected.clone());
- mismatch.actual = table.resolve_completely(mismatch.actual.clone());
- chalk_ir::zip::Zip::zip_with(
- &mut UnknownMismatch(self.db),
- Variance::Invariant,
- &mismatch.expected,
- &mismatch.actual,
- )
- .is_ok()
- });
+ for mismatch in (*type_mismatches).values_mut() {
+ mismatch.expected = table.resolve_completely(mismatch.expected);
+ mismatch.actual = table.resolve_completely(mismatch.actual);
+ }
type_mismatches.shrink_to_fit();
diagnostics.retain_mut(|diagnostic| {
use InferenceDiagnostic::*;
@@ -1001,23 +1054,23 @@ impl<'db> InferenceContext<'db> {
ExpectedFunction { found: ty, .. }
| UnresolvedField { receiver: ty, .. }
| UnresolvedMethodCall { receiver: ty, .. } => {
- *ty = table.resolve_completely(ty.clone());
+ *ty = table.resolve_completely(*ty);
// FIXME: Remove this when we are on par with rustc in terms of inference
- if ty.contains_unknown() {
+ if ty.references_non_lt_error() {
return false;
}
if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic
&& let Some(ty) = field_with_same_name
{
- *ty = table.resolve_completely(ty.clone());
- if ty.contains_unknown() {
+ *ty = table.resolve_completely(*ty);
+ if ty.references_non_lt_error() {
*field_with_same_name = None;
}
}
}
TypedHole { expected: ty, .. } => {
- *ty = table.resolve_completely(ty.clone());
+ *ty = table.resolve_completely(*ty);
}
_ => (),
}
@@ -1025,41 +1078,31 @@ impl<'db> InferenceContext<'db> {
});
diagnostics.shrink_to_fit();
for (_, subst) in method_resolutions.values_mut() {
- *subst =
- table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst.clone());
- *has_errors =
- *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
+ *subst = table.resolve_completely(*subst);
+ *has_errors = *has_errors || subst.types().any(|ty| ty.references_non_lt_error());
}
method_resolutions.shrink_to_fit();
for (_, subst) in assoc_resolutions.values_mut() {
- *subst =
- table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst.clone());
- *has_errors =
- *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
+ *subst = table.resolve_completely(*subst);
+ *has_errors = *has_errors || subst.types().any(|ty| ty.references_non_lt_error());
}
assoc_resolutions.shrink_to_fit();
for adjustment in expr_adjustments.values_mut().flatten() {
- adjustment.target = table.resolve_completely(adjustment.target.clone());
- *has_errors = *has_errors || adjustment.target.contains_unknown();
+ adjustment.target = table.resolve_completely(adjustment.target);
+ *has_errors = *has_errors || adjustment.target.references_non_lt_error();
}
expr_adjustments.shrink_to_fit();
for adjustment in pat_adjustments.values_mut().flatten() {
- *adjustment = table.resolve_completely(adjustment.clone());
- *has_errors = *has_errors || adjustment.contains_unknown();
+ *adjustment = table.resolve_completely(*adjustment);
+ *has_errors = *has_errors || adjustment.references_non_lt_error();
}
pat_adjustments.shrink_to_fit();
result.tuple_field_access_types = tuple_field_accesses_rev
.into_iter()
.enumerate()
- .map(|(idx, subst)| {
- (
- TupleId(idx as u32),
- table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst),
- )
- })
+ .map(|(idx, subst)| (TupleId(idx as u32), table.resolve_completely(subst)))
.inspect(|(_, subst)| {
- *has_errors =
- *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
+ *has_errors = *has_errors || subst.iter().any(|ty| ty.references_non_lt_error());
})
.collect();
result.tuple_field_access_types.shrink_to_fit();
@@ -1074,11 +1117,11 @@ impl<'db> InferenceContext<'db> {
data.type_ref,
&data.store,
InferenceTyDiagnosticSource::Signature,
- LifetimeElisionKind::for_const(id.loc(self.db).container),
+ LifetimeElisionKind::for_const(self.interner(), id.loc(self.db).container),
);
// Constants might be defining usage sites of TAITs.
- self.make_tait_coercion_table(iter::once(&return_ty));
+ self.make_tait_coercion_table(iter::once(return_ty));
self.return_ty = return_ty;
}
@@ -1088,11 +1131,11 @@ impl<'db> InferenceContext<'db> {
data.type_ref,
&data.store,
InferenceTyDiagnosticSource::Signature,
- LifetimeElisionKind::Elided(static_lifetime()),
+ LifetimeElisionKind::Elided(self.types.re_static),
);
// Statics might be defining usage sites of TAITs.
- self.make_tait_coercion_table(iter::once(&return_ty));
+ self.make_tait_coercion_table(iter::once(return_ty));
self.return_ty = return_ty;
}
@@ -1103,25 +1146,28 @@ impl<'db> InferenceContext<'db> {
&data.store,
InferenceTyDiagnosticSource::Signature,
LifetimeElisionKind::for_fn_params(&data),
- |ctx| {
- ctx.type_param_mode(ParamLoweringMode::Placeholder);
- data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>()
- },
+ |ctx| data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>(),
);
// Check if function contains a va_list, if it does then we append it to the parameter types
// that are collected from the function data
if data.is_varargs() {
let va_list_ty = match self.resolve_va_list() {
- Some(va_list) => TyBuilder::adt(self.db, va_list)
- .fill_with_defaults(self.db, || self.table.new_type_var())
- .build(),
+ Some(va_list) => Ty::new_adt(
+ self.interner(),
+ va_list,
+ GenericArgs::for_item_with_defaults(
+ self.interner(),
+ va_list.into(),
+ |_, _, id, _| self.table.next_var_for_param(id),
+ ),
+ ),
None => self.err_ty(),
};
param_tys.push(va_list_ty);
}
- let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var()));
+ let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.next_ty_var()));
if let Some(self_param) = self.body.self_param
&& let Some(ty) = param_tys.next()
{
@@ -1132,12 +1178,8 @@ impl<'db> InferenceContext<'db> {
for (ty, pat) in param_tys.zip(&*self.body.params) {
let ty = self.process_user_written_ty(ty);
- self.infer_top_pat(*pat, &ty, None);
- if ty
- .data(Interner)
- .flags
- .intersects(TypeFlags::HAS_TY_OPAQUE.union(TypeFlags::HAS_TY_INFER))
- {
+ self.infer_top_pat(*pat, ty, None);
+ if ty.flags().intersects(TypeFlags::HAS_TY_OPAQUE.union(TypeFlags::HAS_TY_INFER)) {
tait_candidates.insert(ty);
}
}
@@ -1146,31 +1188,24 @@ impl<'db> InferenceContext<'db> {
let return_ty = self.with_ty_lowering(
&data.store,
InferenceTyDiagnosticSource::Signature,
- LifetimeElisionKind::for_fn_ret(),
+ LifetimeElisionKind::for_fn_ret(self.interner()),
|ctx| {
- ctx.type_param_mode(ParamLoweringMode::Placeholder)
- .impl_trait_mode(ImplTraitLoweringMode::Opaque);
+ ctx.impl_trait_mode(ImplTraitLoweringMode::Opaque);
ctx.lower_ty(return_ty)
},
);
let return_ty = self.insert_type_vars(return_ty);
- if let Some(rpits) = self.db.return_type_impl_traits(func) {
- // RPIT opaque types use substitution of their parent function.
- let fn_placeholders = TyBuilder::placeholder_subst(self.db, func);
+ if let Some(rpits) = self.db.return_type_impl_traits_ns(func) {
let mut mode = ImplTraitReplacingMode::ReturnPosition(FxHashSet::default());
- let result = self.insert_inference_vars_for_impl_trait(
- return_ty,
- fn_placeholders,
- &mut mode,
- );
+ let result = self.insert_inference_vars_for_impl_trait(return_ty, &mut mode);
if let ImplTraitReplacingMode::ReturnPosition(taits) = mode {
tait_candidates.extend(taits);
}
- let rpits = rpits.skip_binders();
+ let rpits = (*rpits).as_ref().skip_binder();
for (id, _) in rpits.impl_traits.iter() {
if let Entry::Vacant(e) = self.result.type_of_rpit.entry(id) {
never!("Missed RPIT in `insert_inference_vars_for_rpit`");
- e.insert(TyKind::Error.intern(Interner));
+ e.insert(self.types.error);
}
}
result
@@ -1178,111 +1213,97 @@ impl<'db> InferenceContext<'db> {
return_ty
}
}
- None => self.result.standard_types.unit.clone(),
+ None => self.types.unit,
};
self.return_ty = self.process_user_written_ty(return_ty);
- self.return_coercion =
- Some(CoerceMany::new(self.return_ty.to_nextsolver(self.table.interner)));
+ self.return_coercion = Some(CoerceMany::new(self.return_ty));
// Functions might be defining usage sites of TAITs.
// To define an TAITs, that TAIT must appear in the function's signatures.
// So, it suffices to check for params and return types.
- fold_tys(
- self.return_ty.clone(),
- |ty, _| {
- match ty.kind(Interner) {
- TyKind::OpaqueType(..)
- | TyKind::Alias(AliasTy::Opaque(..))
- | TyKind::InferenceVar(..) => {
- tait_candidates.insert(self.return_ty.clone());
- }
- _ => {}
+ fold_tys(self.interner(), self.return_ty, |ty| {
+ match ty.kind() {
+ TyKind::Alias(AliasTyKind::Opaque, _) | TyKind::Infer(..) => {
+ tait_candidates.insert(self.return_ty);
}
- ty
- },
- DebruijnIndex::INNERMOST,
- );
+ _ => {}
+ }
+ ty
+ });
+
+ self.make_tait_coercion_table(tait_candidates.iter().copied());
+ }
- self.make_tait_coercion_table(tait_candidates.iter());
+ #[inline]
+ pub(crate) fn interner(&self) -> DbInterner<'db> {
+ self.table.interner()
}
fn insert_inference_vars_for_impl_trait<T>(
&mut self,
t: T,
- placeholders: Substitution,
- mode: &mut ImplTraitReplacingMode,
+ mode: &mut ImplTraitReplacingMode<'db>,
) -> T
where
- T: crate::HasInterner<Interner = Interner> + crate::TypeFoldable<Interner>,
+ T: TypeFoldable<DbInterner<'db>>,
{
- fold_tys(
- t,
- |ty, _| {
- let ty = self.table.structurally_resolve_type(&ty);
- let opaque_ty_id = match ty.kind(Interner) {
- TyKind::OpaqueType(opaque_ty_id, _)
- | TyKind::Alias(AliasTy::Opaque(crate::OpaqueTy { opaque_ty_id, .. })) => {
- *opaque_ty_id
- }
- _ => return ty,
- };
- let (impl_traits, idx) =
- match self.db.lookup_intern_impl_trait_id(opaque_ty_id.into()) {
- // We don't replace opaque types from other kind with inference vars
- // because `insert_inference_vars_for_impl_traits` for each kinds
- // and unreplaced opaque types of other kind are resolved while
- // inferencing because of `tait_coercion_table`.
- // Moreover, calling `insert_inference_vars_for_impl_traits` with same
- // `placeholders` for other kind may cause trouble because
- // the substs for the bounds of each impl traits do not match
- ImplTraitId::ReturnTypeImplTrait(def, idx) => {
- if matches!(mode, ImplTraitReplacingMode::TypeAlias) {
- // RPITs don't have `tait_coercion_table`, so use inserted inference
- // vars for them.
- if let Some(ty) = self.result.type_of_rpit.get(idx) {
- return ty.clone();
- }
- return ty;
- }
- (self.db.return_type_impl_traits(def), idx)
- }
- ImplTraitId::TypeAliasImplTrait(def, idx) => {
- if let ImplTraitReplacingMode::ReturnPosition(taits) = mode {
- // Gather TAITs while replacing RPITs because TAITs inside RPITs
- // may not visited while replacing TAITs
- taits.insert(ty.clone());
- return ty;
- }
- (self.db.type_alias_impl_traits(def), idx)
+ fold_tys(self.interner(), t, |ty| {
+ let ty = self.table.try_structurally_resolve_type(ty);
+ let opaque_ty_id = match ty.kind() {
+ TyKind::Alias(AliasTyKind::Opaque, alias_ty) => alias_ty.def_id.expect_opaque_ty(),
+ _ => return ty,
+ };
+ let (impl_traits, idx) = match self.db.lookup_intern_impl_trait_id(opaque_ty_id) {
+ // We don't replace opaque types from other kind with inference vars
+ // because `insert_inference_vars_for_impl_traits` for each kinds
+ // and unreplaced opaque types of other kind are resolved while
+ // inferencing because of `tait_coercion_table`.
+ ImplTraitId::ReturnTypeImplTrait(def, idx) => {
+ if matches!(mode, ImplTraitReplacingMode::TypeAlias) {
+ // RPITs don't have `tait_coercion_table`, so use inserted inference
+ // vars for them.
+ if let Some(ty) =
+ self.result.type_of_rpit.get(idx.to_nextsolver(self.interner()))
+ {
+ return *ty;
}
- _ => unreachable!(),
- };
- let Some(impl_traits) = impl_traits else {
- return ty;
- };
- let bounds = (*impl_traits)
- .map_ref(|its| its.impl_traits[idx].bounds.map_ref(|it| it.iter()));
- let var = self.table.new_type_var();
- let var_subst = Substitution::from1(Interner, var.clone());
- for bound in bounds {
- let predicate = bound.map(|it| it.cloned());
- let predicate = predicate.substitute(Interner, &placeholders);
- let (var_predicate, binders) =
- predicate.substitute(Interner, &var_subst).into_value_and_skipped_binders();
- always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
- let var_predicate = self.insert_inference_vars_for_impl_trait(
- var_predicate,
- placeholders.clone(),
- mode,
- );
- self.push_obligation(var_predicate.cast(Interner));
+ return ty;
+ }
+ (self.db.return_type_impl_traits_ns(def), idx)
}
- self.result.type_of_rpit.insert(idx, var.clone());
- var
- },
- DebruijnIndex::INNERMOST,
- )
+ ImplTraitId::TypeAliasImplTrait(def, idx) => {
+ if let ImplTraitReplacingMode::ReturnPosition(taits) = mode {
+ // Gather TAITs while replacing RPITs because TAITs inside RPITs
+ // may not visited while replacing TAITs
+ taits.insert(ty);
+ return ty;
+ }
+ (self.db.type_alias_impl_traits_ns(def), idx)
+ }
+ _ => unreachable!(),
+ };
+ let Some(impl_traits) = impl_traits else {
+ return ty;
+ };
+ let bounds = (*impl_traits).as_ref().map_bound(|its| {
+ its.impl_traits[idx.to_nextsolver(self.interner())].predicates.as_slice()
+ });
+ let var = match self.result.type_of_rpit.entry(idx.to_nextsolver(self.interner())) {
+ Entry::Occupied(entry) => return *entry.get(),
+ Entry::Vacant(entry) => *entry.insert(self.table.next_ty_var()),
+ };
+ for clause in bounds.iter_identity_copied() {
+ let clause = self.insert_inference_vars_for_impl_trait(clause, mode);
+ self.table.register_predicate(Obligation::new(
+ self.interner(),
+ ObligationCause::new(),
+ self.table.trait_env.env,
+ clause,
+ ));
+ }
+ var
+ })
}
/// The coercion of a non-inference var into an opaque type should fail,
@@ -1296,51 +1317,38 @@ impl<'db> InferenceContext<'db> {
/// - We are pushing `impl Trait` bounds into it
///
/// This function inserts a map that maps the opaque type to that proxy inference var.
- fn make_tait_coercion_table<'b>(&mut self, tait_candidates: impl Iterator<Item = &'b Ty>) {
- struct TypeAliasImplTraitCollector<'a, 'b> {
- db: &'b dyn HirDatabase,
- table: &'b mut InferenceTable<'a>,
- assocs: FxHashMap<OpaqueTyId, (ImplId, Ty)>,
- non_assocs: FxHashMap<OpaqueTyId, Ty>,
+ fn make_tait_coercion_table(&mut self, tait_candidates: impl Iterator<Item = Ty<'db>>) {
+ struct TypeAliasImplTraitCollector<'a, 'db> {
+ db: &'a dyn HirDatabase,
+ table: &'a mut InferenceTable<'db>,
+ assocs: FxHashMap<InternedOpaqueTyId, (ImplId, Ty<'db>)>,
+ non_assocs: FxHashMap<InternedOpaqueTyId, Ty<'db>>,
}
- impl TypeVisitor<Interner> for TypeAliasImplTraitCollector<'_, '_> {
- type BreakTy = ();
-
- fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
+ impl<'db> TypeVisitor<DbInterner<'db>> for TypeAliasImplTraitCollector<'_, 'db> {
+ type Result = ();
- fn visit_ty(
- &mut self,
- ty: &chalk_ir::Ty<Interner>,
- outer_binder: DebruijnIndex,
- ) -> std::ops::ControlFlow<Self::BreakTy> {
- let ty = self.table.structurally_resolve_type(ty);
+ fn visit_ty(&mut self, ty: Ty<'db>) {
+ let ty = self.table.try_structurally_resolve_type(ty);
- if let TyKind::OpaqueType(id, _)
- | TyKind::Alias(AliasTy::Opaque(crate::OpaqueTy { opaque_ty_id: id, .. })) =
- ty.kind(Interner)
+ if let TyKind::Alias(AliasTyKind::Opaque, alias_ty) = ty.kind()
+ && let id = alias_ty.def_id.expect_opaque_ty()
&& let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
- self.db.lookup_intern_impl_trait_id((*id).into())
+ self.db.lookup_intern_impl_trait_id(id)
{
let loc = self.db.lookup_intern_type_alias(alias_id);
match loc.container {
ItemContainerId::ImplId(impl_id) => {
- self.assocs.insert(*id, (impl_id, ty.clone()));
+ self.assocs.insert(id, (impl_id, ty));
}
ItemContainerId::ModuleId(..) | ItemContainerId::ExternBlockId(..) => {
- self.non_assocs.insert(*id, ty.clone());
+ self.non_assocs.insert(id, ty);
}
_ => {}
}
}
- ty.super_visit_with(self, outer_binder)
+ ty.super_visit_with(self)
}
}
@@ -1351,7 +1359,7 @@ impl<'db> InferenceContext<'db> {
non_assocs: FxHashMap::default(),
};
for ty in tait_candidates {
- _ = ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
+ ty.visit_with(&mut collector);
}
// Non-assoc TAITs can be define-used everywhere as long as they are
@@ -1405,13 +1413,10 @@ impl<'db> InferenceContext<'db> {
let tait_coercion_table: FxHashMap<_, _> = taits
.into_iter()
.filter_map(|(id, ty)| {
- if let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
- self.db.lookup_intern_impl_trait_id(id.into())
+ if let ImplTraitId::TypeAliasImplTrait(..) = self.db.lookup_intern_impl_trait_id(id)
{
- let subst = TyBuilder::placeholder_subst(self.db, alias_id);
let ty = self.insert_inference_vars_for_impl_trait(
ty,
- subst,
&mut ImplTraitReplacingMode::TypeAlias,
);
Some((id, ty))
@@ -1432,18 +1437,18 @@ impl<'db> InferenceContext<'db> {
None => {
_ = self.infer_expr_coerce(
self.body.body_expr,
- &Expectation::has_type(self.return_ty.clone()),
+ &Expectation::has_type(self.return_ty),
ExprIsRead::Yes,
)
}
}
}
- fn write_expr_ty(&mut self, expr: ExprId, ty: Ty) {
+ fn write_expr_ty(&mut self, expr: ExprId, ty: Ty<'db>) {
self.result.type_of_expr.insert(expr, ty);
}
- fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment]>) {
+ fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment<'db>]>) {
if adjustments.is_empty() {
return;
}
@@ -1456,7 +1461,7 @@ impl<'db> InferenceContext<'db> {
) => {
// NeverToAny coercion can target any type, so instead of adding a new
// adjustment on top we can change the target.
- *target = new_target.clone();
+ *target = *new_target;
}
_ => {
*entry.get_mut() = adjustments;
@@ -1469,14 +1474,14 @@ impl<'db> InferenceContext<'db> {
}
}
- fn write_pat_adj(&mut self, pat: PatId, adjustments: Box<[Ty]>) {
+ fn write_pat_adj(&mut self, pat: PatId, adjustments: Box<[Ty<'db>]>) {
if adjustments.is_empty() {
return;
}
self.result.pat_adjustments.entry(pat).or_default().extend(adjustments);
}
- fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) {
+ fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: GenericArgs<'db>) {
self.result.method_resolutions.insert(expr, (func, subst));
}
@@ -1484,19 +1489,24 @@ impl<'db> InferenceContext<'db> {
self.result.variant_resolutions.insert(id, variant);
}
- fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItemId, subs: Substitution) {
+ fn write_assoc_resolution(
+ &mut self,
+ id: ExprOrPatId,
+ item: AssocItemId,
+ subs: GenericArgs<'db>,
+ ) {
self.result.assoc_resolutions.insert(id, (item, subs));
}
- fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
+ fn write_pat_ty(&mut self, pat: PatId, ty: Ty<'db>) {
self.result.type_of_pat.insert(pat, ty);
}
- fn write_binding_ty(&mut self, id: BindingId, ty: Ty) {
+ fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) {
self.result.type_of_binding.insert(id, ty);
}
- fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) {
+ fn push_diagnostic(&self, diagnostic: InferenceDiagnostic<'db>) {
self.diagnostics.push(diagnostic);
}
@@ -1504,8 +1514,8 @@ impl<'db> InferenceContext<'db> {
&mut self,
store: &ExpressionStore,
types_source: InferenceTyDiagnosticSource,
- lifetime_elision: LifetimeElisionKind,
- f: impl FnOnce(&mut TyLoweringContext<'_>) -> R,
+ lifetime_elision: LifetimeElisionKind<'db>,
+ f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,
) -> R {
let mut ctx = TyLoweringContext::new(
self.db,
@@ -1519,7 +1529,10 @@ impl<'db> InferenceContext<'db> {
f(&mut ctx)
}
- fn with_body_ty_lowering<R>(&mut self, f: impl FnOnce(&mut TyLoweringContext<'_>) -> R) -> R {
+ fn with_body_ty_lowering<R>(
+ &mut self,
+ f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,
+ ) -> R {
self.with_ty_lowering(
self.body,
InferenceTyDiagnosticSource::Body,
@@ -1533,14 +1546,14 @@ impl<'db> InferenceContext<'db> {
type_ref: TypeRefId,
store: &ExpressionStore,
type_source: InferenceTyDiagnosticSource,
- lifetime_elision: LifetimeElisionKind,
- ) -> Ty {
+ lifetime_elision: LifetimeElisionKind<'db>,
+ ) -> Ty<'db> {
let ty = self
.with_ty_lowering(store, type_source, lifetime_elision, |ctx| ctx.lower_ty(type_ref));
self.process_user_written_ty(ty)
}
- fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty {
+ fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
self.make_ty(
type_ref,
self.body,
@@ -1549,37 +1562,31 @@ impl<'db> InferenceContext<'db> {
)
}
- fn make_body_const(&mut self, const_ref: ConstRef, ty: Ty) -> Const {
+ fn make_body_const(&mut self, const_ref: ConstRef, ty: Ty<'db>) -> Const<'db> {
let const_ = self.with_ty_lowering(
self.body,
InferenceTyDiagnosticSource::Body,
LifetimeElisionKind::Infer,
- |ctx| {
- ctx.type_param_mode = ParamLoweringMode::Placeholder;
- ctx.lower_const(&const_ref, ty)
- },
+ |ctx| ctx.lower_const(const_ref, ty),
);
self.insert_type_vars(const_)
}
- fn make_path_as_body_const(&mut self, path: &Path, ty: Ty) -> Const {
+ fn make_path_as_body_const(&mut self, path: &Path, ty: Ty<'db>) -> Const<'db> {
let const_ = self.with_ty_lowering(
self.body,
InferenceTyDiagnosticSource::Body,
LifetimeElisionKind::Infer,
- |ctx| {
- ctx.type_param_mode = ParamLoweringMode::Placeholder;
- ctx.lower_path_as_const(path, ty)
- },
+ |ctx| ctx.lower_path_as_const(path, ty),
);
self.insert_type_vars(const_)
}
- fn err_ty(&self) -> Ty {
- self.result.standard_types.unknown.clone()
+ fn err_ty(&self) -> Ty<'db> {
+ self.types.error
}
- fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Lifetime {
+ fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Region<'db> {
let lt = self.with_ty_lowering(
self.body,
InferenceTyDiagnosticSource::Body,
@@ -1590,44 +1597,25 @@ impl<'db> InferenceContext<'db> {
}
/// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
- fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
+ fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> {
self.table.insert_type_vars_shallow(ty)
}
fn insert_type_vars<T>(&mut self, ty: T) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
+ T: TypeFoldable<DbInterner<'db>>,
{
self.table.insert_type_vars(ty)
}
- fn push_obligation(&mut self, o: DomainGoal) {
- let goal: crate::Goal = o.cast(Interner);
- self.table.register_obligation(goal.to_nextsolver(self.table.interner));
- }
-
- fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
- let ty1 = ty1
- .clone()
- .try_fold_with(
- &mut UnevaluatedConstEvaluatorFolder { db: self.db },
- DebruijnIndex::INNERMOST,
- )
- .unwrap();
- let ty2 = ty2
- .clone()
- .try_fold_with(
- &mut UnevaluatedConstEvaluatorFolder { db: self.db },
- DebruijnIndex::INNERMOST,
- )
- .unwrap();
- self.table.unify(&ty1, &ty2)
+ fn unify(&mut self, ty1: Ty<'db>, ty2: Ty<'db>) -> bool {
+ self.table.unify(ty1, ty2)
}
/// Attempts to returns the deeply last field of nested structures, but
/// does not apply any normalization in its search. Returns the same type
/// if input `ty` is not a structure at all.
- fn struct_tail_without_normalization(&mut self, ty: Ty) -> Ty {
+ fn struct_tail_without_normalization(&mut self, ty: Ty<'db>) -> Ty<'db> {
self.struct_tail_with_normalize(ty, identity)
}
@@ -1640,37 +1628,34 @@ impl<'db> InferenceContext<'db> {
/// function to indicate no normalization should take place.
fn struct_tail_with_normalize(
&mut self,
- mut ty: Ty,
- mut normalize: impl FnMut(Ty) -> Ty,
- ) -> Ty {
+ mut ty: Ty<'db>,
+ mut normalize: impl FnMut(Ty<'db>) -> Ty<'db>,
+ ) -> Ty<'db> {
// FIXME: fetch the limit properly
let recursion_limit = 10;
for iteration in 0.. {
if iteration > recursion_limit {
return self.err_ty();
}
- match ty.kind(Interner) {
- TyKind::Adt(chalk_ir::AdtId(hir_def::AdtId::StructId(struct_id)), substs) => {
- match self.db.field_types((*struct_id).into()).values().next_back().cloned() {
- Some(field) => {
- ty = field.substitute(Interner, substs);
+ 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()
+ {
+ Some(field) => {
+ ty = field.instantiate(self.interner(), substs);
+ }
+ None => break,
}
- None => break,
- }
- }
- TyKind::Adt(..) => break,
- TyKind::Tuple(_, substs) => {
- match substs
- .as_slice(Interner)
- .split_last()
- .and_then(|(last_ty, _)| last_ty.ty(Interner))
- {
- Some(last_ty) => ty = last_ty.clone(),
- None => break,
}
- }
+ _ => break,
+ },
+ TyKind::Tuple(substs) => match substs.as_slice().split_last() {
+ Some((last_ty, _)) => ty = *last_ty,
+ None => break,
+ },
TyKind::Alias(..) => {
- let normalized = normalize(ty.clone());
+ let normalized = normalize(ty);
if ty == normalized {
return ty;
} else {
@@ -1684,41 +1669,35 @@ impl<'db> InferenceContext<'db> {
}
/// Whenever you lower a user-written type, you should call this.
- fn process_user_written_ty<T, U>(&mut self, ty: T) -> T
+ fn process_user_written_ty<T>(&mut self, ty: T) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>,
- U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
+ T: TypeFoldable<DbInterner<'db>>,
{
self.table.process_user_written_ty(ty)
}
/// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
/// while `process_user_written_ty()` should (but doesn't currently).
- fn process_remote_user_written_ty<T, U>(&mut self, ty: T) -> T
+ fn process_remote_user_written_ty<T>(&mut self, ty: T) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>,
- U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
+ T: TypeFoldable<DbInterner<'db>>,
{
self.table.process_remote_user_written_ty(ty)
}
- fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
- self.table.resolve_ty_shallow(ty)
- }
-
- fn shallow_resolve(&self, ty: crate::next_solver::Ty<'db>) -> crate::next_solver::Ty<'db> {
+ fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {
self.table.shallow_resolve(ty)
}
- fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
+ fn resolve_associated_type(
+ &mut self,
+ inner_ty: Ty<'db>,
+ assoc_ty: Option<TypeAliasId>,
+ ) -> Ty<'db> {
self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])
}
- fn demand_eqtype(
- &mut self,
- expected: crate::next_solver::Ty<'db>,
- actual: crate::next_solver::Ty<'db>,
- ) {
+ fn demand_eqtype(&mut self, expected: Ty<'db>, actual: Ty<'db>) {
let result = self
.table
.infer_ctxt
@@ -1732,34 +1711,24 @@ impl<'db> InferenceContext<'db> {
fn resolve_associated_type_with_params(
&mut self,
- inner_ty: Ty,
+ inner_ty: Ty<'db>,
assoc_ty: Option<TypeAliasId>,
// FIXME(GATs): these are args for the trait ref, args for assoc type itself should be
// handled when we support them.
- params: &[GenericArg],
- ) -> Ty {
+ params: &[GenericArg<'db>],
+ ) -> Ty<'db> {
match assoc_ty {
Some(res_assoc_ty) => {
- let trait_ = match res_assoc_ty.lookup(self.db).container {
- hir_def::ItemContainerId::TraitId(trait_) => trait_,
- _ => panic!("resolve_associated_type called with non-associated type"),
- };
- let ty = self.table.new_type_var();
- let mut param_iter = params.iter().cloned();
- let trait_ref = TyBuilder::trait_ref(self.db, trait_)
- .push(inner_ty)
- .fill(|_| param_iter.next().unwrap())
- .build();
- let alias_eq = AliasEq {
- alias: AliasTy::Projection(ProjectionTy {
- associated_ty_id: to_assoc_type_id(res_assoc_ty),
- substitution: trait_ref.substitution.clone(),
- }),
- ty: ty.clone(),
- };
- self.push_obligation(trait_ref.cast(Interner));
- self.push_obligation(alias_eq.cast(Interner));
- ty
+ let alias = Ty::new_alias(
+ self.interner(),
+ AliasTyKind::Projection,
+ AliasTy::new(
+ self.interner(),
+ res_assoc_ty.into(),
+ iter::once(inner_ty.into()).chain(params.iter().copied()),
+ ),
+ );
+ self.table.try_structurally_resolve_type(alias)
}
None => self.err_ty(),
}
@@ -1770,7 +1739,7 @@ impl<'db> InferenceContext<'db> {
node: ExprOrPatId,
path: Option<&Path>,
value_ns: bool,
- ) -> (Ty, Option<VariantId>) {
+ ) -> (Ty<'db>, Option<VariantId>) {
let path = match path {
Some(path) => path,
None => return (self.err_ty(), None),
@@ -1793,28 +1762,19 @@ impl<'db> InferenceContext<'db> {
match res {
ResolveValueResult::ValueNs(value, _) => match value {
ValueNs::EnumVariantId(var) => {
- let substs = path_ctx.substs_from_path(var.into(), true, false);
+ let args = path_ctx.substs_from_path(var.into(), true, false);
drop(ctx);
- let args: crate::next_solver::GenericArgs<'_> =
- substs.to_nextsolver(interner);
let ty = self
.db
.ty(var.lookup(self.db).parent.into())
- .instantiate(interner, args)
- .to_chalk(interner);
+ .instantiate(interner, args);
let ty = self.insert_type_vars(ty);
return (ty, Some(var.into()));
}
ValueNs::StructId(strukt) => {
- let substs = path_ctx.substs_from_path(strukt.into(), true, false);
+ let args = path_ctx.substs_from_path(strukt.into(), true, false);
drop(ctx);
- let args: crate::next_solver::GenericArgs<'_> =
- substs.to_nextsolver(interner);
- let ty = self
- .db
- .ty(strukt.into())
- .instantiate(interner, args)
- .to_chalk(interner);
+ let ty = self.db.ty(strukt.into()).instantiate(interner, args);
let ty = self.insert_type_vars(ty);
return (ty, Some(strukt.into()));
}
@@ -1834,39 +1794,28 @@ impl<'db> InferenceContext<'db> {
};
return match resolution {
TypeNs::AdtId(AdtId::StructId(strukt)) => {
- let substs = path_ctx.substs_from_path(strukt.into(), true, false);
+ let args = path_ctx.substs_from_path(strukt.into(), true, false);
drop(ctx);
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- let ty = self.db.ty(strukt.into()).instantiate(interner, args).to_chalk(interner);
+ let ty = self.db.ty(strukt.into()).instantiate(interner, args);
let ty = self.insert_type_vars(ty);
- forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
+ forbid_unresolved_segments(self, (ty, Some(strukt.into())), unresolved)
}
TypeNs::AdtId(AdtId::UnionId(u)) => {
- let substs = path_ctx.substs_from_path(u.into(), true, false);
+ let args = path_ctx.substs_from_path(u.into(), true, false);
drop(ctx);
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- let ty = self.db.ty(u.into()).instantiate(interner, args).to_chalk(interner);
+ let ty = self.db.ty(u.into()).instantiate(interner, args);
let ty = self.insert_type_vars(ty);
- forbid_unresolved_segments((ty, Some(u.into())), unresolved)
+ forbid_unresolved_segments(self, (ty, Some(u.into())), unresolved)
}
TypeNs::EnumVariantId(var) => {
- let substs = path_ctx.substs_from_path(var.into(), true, false);
+ let args = path_ctx.substs_from_path(var.into(), true, false);
drop(ctx);
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- let ty = self
- .db
- .ty(var.lookup(self.db).parent.into())
- .instantiate(interner, args)
- .to_chalk(interner);
+ let ty = self.db.ty(var.lookup(self.db).parent.into()).instantiate(interner, args);
let ty = self.insert_type_vars(ty);
- forbid_unresolved_segments((ty, Some(var.into())), unresolved)
+ forbid_unresolved_segments(self, (ty, Some(var.into())), unresolved)
}
TypeNs::SelfType(impl_id) => {
- let generics = crate::generics::generics(self.db, impl_id.into());
- let substs = generics.placeholder_subst(self.db);
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- let mut ty =
- self.db.impl_self_ty(impl_id).instantiate(interner, args).to_chalk(interner);
+ let mut ty = self.db.impl_self_ty(impl_id).instantiate_identity();
let Some(remaining_idx) = unresolved else {
drop(ctx);
@@ -1889,7 +1838,9 @@ impl<'db> InferenceContext<'db> {
while let Some(current_segment) = remaining_segments.first() {
// If we can resolve to an enum variant, it takes priority over associated type
// of the same name.
- if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
+ if let TyKind::Adt(adt_def, _) = ty.kind()
+ && let AdtId::EnumId(id) = adt_def.def_id().0
+ {
let enum_data = id.enum_variants(self.db);
if let Some(variant) = enum_data.variant(current_segment.name) {
return if remaining_segments.len() == 1 {
@@ -1917,8 +1868,8 @@ impl<'db> InferenceContext<'db> {
ty = self.table.insert_type_vars(ty);
ty = self.table.normalize_associated_types_in(ty);
- ty = self.table.structurally_resolve_type(&ty);
- if ty.is_unknown() {
+ ty = self.table.structurally_resolve_type(ty);
+ if ty.is_ty_error() {
return (self.err_ty(), None);
}
@@ -1941,11 +1892,10 @@ impl<'db> InferenceContext<'db> {
never!("resolver should always resolve lang item paths");
return (self.err_ty(), None);
};
- let substs = path_ctx.substs_from_path_segment(it.into(), true, None, false);
+ let args = path_ctx.substs_from_path_segment(it.into(), true, None, false);
drop(ctx);
let interner = DbInterner::conjure();
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- let ty = self.db.ty(it.into()).instantiate(interner, args).to_chalk(interner);
+ let ty = self.db.ty(it.into()).instantiate(interner, args);
let ty = self.insert_type_vars(ty);
self.resolve_variant_on_alias(ty, unresolved, mod_path)
@@ -1967,33 +1917,28 @@ impl<'db> InferenceContext<'db> {
}
};
- fn forbid_unresolved_segments(
- result: (Ty, Option<VariantId>),
+ fn forbid_unresolved_segments<'db>(
+ ctx: &InferenceContext<'_, 'db>,
+ result: (Ty<'db>, Option<VariantId>),
unresolved: Option<usize>,
- ) -> (Ty, Option<VariantId>) {
+ ) -> (Ty<'db>, Option<VariantId>) {
if unresolved.is_none() {
result
} else {
// FIXME diagnostic
- (TyKind::Error.intern(Interner), None)
+ (ctx.types.error, None)
}
}
}
fn resolve_variant_on_alias(
&mut self,
- ty: Ty,
+ ty: Ty<'db>,
unresolved: Option<usize>,
path: &ModPath,
- ) -> (Ty, Option<VariantId>) {
+ ) -> (Ty<'db>, Option<VariantId>) {
let remaining = unresolved.map(|it| path.segments()[it..].len()).filter(|it| it > &0);
- let ty = match ty.kind(Interner) {
- TyKind::Alias(AliasTy::Projection(proj_ty)) => {
- let ty = self.table.normalize_projection_ty(proj_ty.clone());
- self.table.structurally_resolve_type(&ty)
- }
- _ => ty,
- };
+ let ty = self.table.try_structurally_resolve_type(ty);
match remaining {
None => {
let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
@@ -2115,19 +2060,18 @@ impl<'db> InferenceContext<'db> {
/// When inferring an expression, we propagate downward whatever type hint we
/// are able in the form of an `Expectation`.
#[derive(Clone, PartialEq, Eq, Debug)]
-pub(crate) enum Expectation {
+pub(crate) enum Expectation<'db> {
None,
- HasType(Ty),
- #[allow(dead_code)]
- Castable(Ty),
- RValueLikeUnsized(Ty),
+ HasType(Ty<'db>),
+ Castable(Ty<'db>),
+ RValueLikeUnsized(Ty<'db>),
}
-impl Expectation {
+impl<'db> Expectation<'db> {
/// The expectation that the type of the expression needs to equal the given
/// type.
- fn has_type(ty: Ty) -> Self {
- if ty.is_unknown() {
+ fn has_type(ty: Ty<'db>) -> Self {
+ if ty.is_ty_error() {
// FIXME: get rid of this?
Expectation::None
} else {
@@ -2155,9 +2099,11 @@ impl Expectation {
/// which still is useful, because it informs integer literals and the like.
/// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
/// for examples of where this comes up,.
- fn rvalue_hint(ctx: &mut InferenceContext<'_>, ty: Ty) -> Self {
- match ctx.struct_tail_without_normalization(ty.clone()).kind(Interner) {
- TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => Expectation::RValueLikeUnsized(ty),
+ fn rvalue_hint(ctx: &mut InferenceContext<'_, 'db>, ty: Ty<'db>) -> Self {
+ match ctx.struct_tail_without_normalization(ty).kind() {
+ TyKind::Slice(_) | TyKind::Str | TyKind::Dynamic(..) => {
+ Expectation::RValueLikeUnsized(ty)
+ }
_ => Expectation::has_type(ty),
}
}
@@ -2167,18 +2113,18 @@ impl Expectation {
Expectation::None
}
- fn resolve(&self, table: &mut unify::InferenceTable<'_>) -> Expectation {
+ fn resolve(&self, table: &mut unify::InferenceTable<'db>) -> Expectation<'db> {
match self {
Expectation::None => Expectation::None,
- Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)),
- Expectation::Castable(t) => Expectation::Castable(table.resolve_ty_shallow(t)),
+ Expectation::HasType(t) => Expectation::HasType(table.shallow_resolve(*t)),
+ Expectation::Castable(t) => Expectation::Castable(table.shallow_resolve(*t)),
Expectation::RValueLikeUnsized(t) => {
- Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t))
+ Expectation::RValueLikeUnsized(table.shallow_resolve(*t))
}
}
}
- fn to_option(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
+ fn to_option(&self, table: &mut unify::InferenceTable<'db>) -> Option<Ty<'db>> {
match self.resolve(table) {
Expectation::None => None,
Expectation::HasType(t)
@@ -2187,17 +2133,17 @@ impl Expectation {
}
}
- fn only_has_type(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
+ fn only_has_type(&self, table: &mut unify::InferenceTable<'db>) -> Option<Ty<'db>> {
match self {
- Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)),
+ Expectation::HasType(t) => Some(table.shallow_resolve(*t)),
Expectation::Castable(_) | Expectation::RValueLikeUnsized(_) | Expectation::None => {
None
}
}
}
- fn coercion_target_type(&self, table: &mut unify::InferenceTable<'_>) -> Ty {
- self.only_has_type(table).unwrap_or_else(|| table.new_type_var())
+ fn coercion_target_type(&self, table: &mut unify::InferenceTable<'db>) -> Ty<'db> {
+ self.only_has_type(table).unwrap_or_else(|| table.next_ty_var())
}
/// Comment copied from rustc:
@@ -2217,13 +2163,13 @@ impl Expectation {
/// an expected type. Otherwise, we might write parts of the type
/// when checking the 'then' block which are incompatible with the
/// 'else' branch.
- fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation {
- match self {
+ fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'db>) -> Expectation<'db> {
+ match *self {
Expectation::HasType(ety) => {
let ety = table.structurally_resolve_type(ety);
if ety.is_ty_var() { Expectation::None } else { Expectation::HasType(ety) }
}
- Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()),
+ Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety),
_ => Expectation::None,
}
}
@@ -2266,123 +2212,3 @@ impl std::ops::BitOrAssign for Diverges {
*self = *self | other;
}
}
-
-/// A zipper that checks for unequal occurrences of `{unknown}` and unresolved projections
-/// in the two types. Used to filter out mismatch diagnostics that only differ in
-/// `{unknown}` and unresolved projections. These mismatches are usually not helpful.
-/// As the cause is usually an underlying name resolution problem
-struct UnknownMismatch<'db>(&'db dyn HirDatabase);
-impl chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_> {
- fn zip_tys(&mut self, variance: Variance, a: &Ty, b: &Ty) -> chalk_ir::Fallible<()> {
- let zip_substs = |this: &mut Self,
- variances,
- sub_a: &Substitution,
- sub_b: &Substitution| {
- this.zip_substs(variance, variances, sub_a.as_slice(Interner), sub_b.as_slice(Interner))
- };
- match (a.kind(Interner), b.kind(Interner)) {
- (TyKind::Adt(id_a, sub_a), TyKind::Adt(id_b, sub_b)) if id_a == id_b => zip_substs(
- self,
- Some(self.unification_database().adt_variance(*id_a)),
- sub_a,
- sub_b,
- )?,
- (
- TyKind::AssociatedType(assoc_ty_a, sub_a),
- TyKind::AssociatedType(assoc_ty_b, sub_b),
- ) if assoc_ty_a == assoc_ty_b => zip_substs(self, None, sub_a, sub_b)?,
- (TyKind::Tuple(arity_a, sub_a), TyKind::Tuple(arity_b, sub_b))
- if arity_a == arity_b =>
- {
- zip_substs(self, None, sub_a, sub_b)?
- }
- (TyKind::OpaqueType(opaque_ty_a, sub_a), TyKind::OpaqueType(opaque_ty_b, sub_b))
- if opaque_ty_a == opaque_ty_b =>
- {
- zip_substs(self, None, sub_a, sub_b)?
- }
- (TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => self.zip_tys(variance, ty_a, ty_b)?,
- (TyKind::FnDef(fn_def_a, sub_a), TyKind::FnDef(fn_def_b, sub_b))
- if fn_def_a == fn_def_b =>
- {
- zip_substs(
- self,
- Some(self.unification_database().fn_def_variance(*fn_def_a)),
- sub_a,
- sub_b,
- )?
- }
- (TyKind::Ref(mutability_a, _, ty_a), TyKind::Ref(mutability_b, _, ty_b))
- if mutability_a == mutability_b =>
- {
- self.zip_tys(variance, ty_a, ty_b)?
- }
- (TyKind::Raw(mutability_a, ty_a), TyKind::Raw(mutability_b, ty_b))
- if mutability_a == mutability_b =>
- {
- self.zip_tys(variance, ty_a, ty_b)?
- }
- (TyKind::Array(ty_a, const_a), TyKind::Array(ty_b, const_b)) if const_a == const_b => {
- self.zip_tys(variance, ty_a, ty_b)?
- }
- (TyKind::Closure(id_a, sub_a), TyKind::Closure(id_b, sub_b)) if id_a == id_b => {
- zip_substs(self, None, sub_a, sub_b)?
- }
- (TyKind::Coroutine(coroutine_a, sub_a), TyKind::Coroutine(coroutine_b, sub_b))
- if coroutine_a == coroutine_b =>
- {
- zip_substs(self, None, sub_a, sub_b)?
- }
- (
- TyKind::CoroutineWitness(coroutine_a, sub_a),
- TyKind::CoroutineWitness(coroutine_b, sub_b),
- ) if coroutine_a == coroutine_b => zip_substs(self, None, sub_a, sub_b)?,
- (TyKind::Function(fn_ptr_a), TyKind::Function(fn_ptr_b))
- if fn_ptr_a.sig == fn_ptr_b.sig && fn_ptr_a.num_binders == fn_ptr_b.num_binders =>
- {
- zip_substs(self, None, &fn_ptr_a.substitution.0, &fn_ptr_b.substitution.0)?
- }
- (TyKind::Error, TyKind::Error) => (),
- (TyKind::Error, _)
- | (_, TyKind::Error)
- | (TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _), _)
- | (_, TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _)) => {
- return Err(chalk_ir::NoSolution);
- }
- _ => (),
- }
-
- Ok(())
- }
-
- fn zip_lifetimes(&mut self, _: Variance, _: &Lifetime, _: &Lifetime) -> chalk_ir::Fallible<()> {
- Ok(())
- }
-
- fn zip_consts(&mut self, _: Variance, _: &Const, _: &Const) -> chalk_ir::Fallible<()> {
- Ok(())
- }
-
- fn zip_binders<T>(
- &mut self,
- variance: Variance,
- a: &Binders<T>,
- b: &Binders<T>,
- ) -> chalk_ir::Fallible<()>
- where
- T: Clone
- + HasInterner<Interner = Interner>
- + chalk_ir::zip::Zip<Interner>
- + TypeFoldable<Interner>,
- {
- chalk_ir::zip::Zip::zip_with(self, variance, a.skip_binders(), b.skip_binders())
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
-
- fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> {
- &self.0
- }
-}
diff --git a/crates/hir-ty/src/infer/autoderef.rs b/crates/hir-ty/src/infer/autoderef.rs
index 77b1ae6a94..ba133aa553 100644
--- a/crates/hir-ty/src/infer/autoderef.rs
+++ b/crates/hir-ty/src/infer/autoderef.rs
@@ -2,6 +2,8 @@
use std::iter;
+use rustc_ast_ir::Mutability;
+
use crate::{
Adjust, Adjustment, OverloadedDeref,
autoderef::{Autoderef, AutoderefKind},
@@ -9,7 +11,6 @@ use crate::{
next_solver::{
Ty,
infer::{InferOk, traits::PredicateObligations},
- mapping::NextSolverToChalk,
},
};
@@ -21,12 +22,12 @@ impl<'db> InferenceTable<'db> {
impl<'db> Autoderef<'_, 'db> {
/// Returns the adjustment steps.
- pub(crate) fn adjust_steps(mut self) -> Vec<Adjustment> {
+ pub(crate) fn adjust_steps(mut self) -> Vec<Adjustment<'db>> {
let infer_ok = self.adjust_steps_as_infer_ok();
self.table.register_infer_ok(infer_ok)
}
- pub(crate) fn adjust_steps_as_infer_ok(&mut self) -> InferOk<'db, Vec<Adjustment>> {
+ pub(crate) fn adjust_steps_as_infer_ok(&mut self) -> InferOk<'db, Vec<Adjustment<'db>>> {
let steps = self.steps();
if steps.is_empty() {
return InferOk { obligations: PredicateObligations::new(), value: vec![] };
@@ -37,16 +38,13 @@ impl<'db> Autoderef<'_, 'db> {
.iter()
.map(|&(_source, kind)| {
if let AutoderefKind::Overloaded = kind {
- Some(OverloadedDeref(Some(chalk_ir::Mutability::Not)))
+ Some(OverloadedDeref(Some(Mutability::Not)))
} else {
None
}
})
.zip(targets)
- .map(|(autoderef, target)| Adjustment {
- kind: Adjust::Deref(autoderef),
- target: target.to_chalk(self.table.interner),
- })
+ .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })
.collect();
InferOk { obligations: self.take_obligations(), value: steps }
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs
index 4cd6144a14..017f45f43d 100644
--- a/crates/hir-ty/src/infer/cast.rs
+++ b/crates/hir-ty/src/infer/cast.rs
@@ -1,17 +1,18 @@
//! Type cast logic. Basically coercion + additional casts.
-use chalk_ir::{Mutability, Scalar, TyVariableKind, UintTy};
use hir_def::{AdtId, hir::ExprId, signatures::TraitFlags};
+use rustc_ast_ir::Mutability;
+use rustc_type_ir::{
+ Flags, InferTy, TypeFlags, UintTy,
+ inherent::{AdtDef, BoundExistentialPredicates as _, IntoKind, SliceLike, Ty as _},
+};
use stdx::never;
-use crate::infer::coerce::CoerceNever;
use crate::{
- Binders, DynTy, InferenceDiagnostic, Interner, PlaceholderIndex, QuantifiedWhereClauses, Ty,
- TyExt, TyKind, TypeFlags, WhereClause,
+ InferenceDiagnostic,
db::HirDatabase,
- from_chalk_trait_id,
- infer::{AllowTwoPhase, InferenceContext},
- next_solver::mapping::ChalkToNextSolver,
+ infer::{AllowTwoPhase, InferenceContext, coerce::CoerceNever},
+ next_solver::{BoundExistentialPredicates, DbInterner, ParamTy, Ty, TyKind},
};
#[derive(Debug)]
@@ -25,24 +26,24 @@ pub(crate) enum Int {
}
#[derive(Debug)]
-pub(crate) enum CastTy {
+pub(crate) enum CastTy<'db> {
Int(Int),
Float,
FnPtr,
- Ptr(Ty, Mutability),
+ Ptr(Ty<'db>, Mutability),
// `DynStar` is Not supported yet in r-a
}
-impl CastTy {
- pub(crate) fn from_ty(db: &dyn HirDatabase, t: &Ty) -> Option<Self> {
- match t.kind(Interner) {
- TyKind::Scalar(Scalar::Bool) => Some(Self::Int(Int::Bool)),
- TyKind::Scalar(Scalar::Char) => Some(Self::Int(Int::Char)),
- TyKind::Scalar(Scalar::Int(_)) => Some(Self::Int(Int::I)),
- TyKind::Scalar(Scalar::Uint(it)) => Some(Self::Int(Int::U(*it))),
- TyKind::InferenceVar(_, TyVariableKind::Integer) => Some(Self::Int(Int::InferenceVar)),
- TyKind::InferenceVar(_, TyVariableKind::Float) => Some(Self::Float),
- TyKind::Scalar(Scalar::Float(_)) => Some(Self::Float),
+impl<'db> CastTy<'db> {
+ pub(crate) fn from_ty(db: &dyn HirDatabase, t: Ty<'db>) -> Option<Self> {
+ match t.kind() {
+ TyKind::Bool => Some(Self::Int(Int::Bool)),
+ TyKind::Char => Some(Self::Int(Int::Char)),
+ TyKind::Int(_) => Some(Self::Int(Int::I)),
+ TyKind::Uint(it) => Some(Self::Int(Int::U(it))),
+ TyKind::Infer(InferTy::IntVar(_)) => Some(Self::Int(Int::InferenceVar)),
+ TyKind::Infer(InferTy::FloatVar(_)) => Some(Self::Float),
+ TyKind::Float(_) => Some(Self::Float),
TyKind::Adt(..) => {
let (AdtId::EnumId(id), _) = t.as_adt()? else {
return None;
@@ -50,8 +51,8 @@ impl CastTy {
let enum_data = id.enum_variants(db);
if enum_data.is_payload_free(db) { Some(Self::Int(Int::CEnum)) } else { None }
}
- TyKind::Raw(m, ty) => Some(Self::Ptr(ty.clone(), *m)),
- TyKind::Function(_) => Some(Self::FnPtr),
+ TyKind::RawPtr(ty, m) => Some(Self::Ptr(ty, m)),
+ TyKind::FnPtr(..) => Some(Self::FnPtr),
_ => None,
}
}
@@ -77,37 +78,47 @@ pub enum CastError {
}
impl CastError {
- fn into_diagnostic(self, expr: ExprId, expr_ty: Ty, cast_ty: Ty) -> InferenceDiagnostic {
+ fn into_diagnostic<'db>(
+ self,
+ expr: ExprId,
+ expr_ty: Ty<'db>,
+ cast_ty: Ty<'db>,
+ ) -> InferenceDiagnostic<'db> {
InferenceDiagnostic::InvalidCast { expr, error: self, expr_ty, cast_ty }
}
}
#[derive(Clone, Debug)]
-pub(super) struct CastCheck {
+pub(super) struct CastCheck<'db> {
expr: ExprId,
source_expr: ExprId,
- expr_ty: Ty,
- cast_ty: Ty,
+ expr_ty: Ty<'db>,
+ cast_ty: Ty<'db>,
}
-impl CastCheck {
- pub(super) fn new(expr: ExprId, source_expr: ExprId, expr_ty: Ty, cast_ty: Ty) -> Self {
+impl<'db> CastCheck<'db> {
+ pub(super) fn new(
+ expr: ExprId,
+ source_expr: ExprId,
+ expr_ty: Ty<'db>,
+ cast_ty: Ty<'db>,
+ ) -> Self {
Self { expr, source_expr, expr_ty, cast_ty }
}
pub(super) fn check(
&mut self,
- ctx: &mut InferenceContext<'_>,
- ) -> Result<(), InferenceDiagnostic> {
- self.expr_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.expr_ty.clone());
- self.cast_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.cast_ty.clone());
+ ctx: &mut InferenceContext<'_, 'db>,
+ ) -> Result<(), InferenceDiagnostic<'db>> {
+ self.expr_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.expr_ty);
+ self.cast_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.cast_ty);
// This should always come first so that we apply the coercion, which impacts infer vars.
if ctx
.coerce(
self.source_expr.into(),
- self.expr_ty.to_nextsolver(ctx.table.interner),
- self.cast_ty.to_nextsolver(ctx.table.interner),
+ self.expr_ty,
+ self.cast_ty,
AllowTwoPhase::No,
CoerceNever::Yes,
)
@@ -117,83 +128,82 @@ impl CastCheck {
return Ok(());
}
- if self.expr_ty.contains_unknown() || self.cast_ty.contains_unknown() {
+ if self.expr_ty.references_non_lt_error() || self.cast_ty.references_non_lt_error() {
return Ok(());
}
- if !self.cast_ty.data(Interner).flags.contains(TypeFlags::HAS_TY_INFER)
- && !ctx.table.is_sized(&self.cast_ty)
+ if !self.cast_ty.flags().contains(TypeFlags::HAS_TY_INFER)
+ && !ctx.table.is_sized(self.cast_ty)
{
return Err(InferenceDiagnostic::CastToUnsized {
expr: self.expr,
- cast_ty: self.cast_ty.clone(),
+ cast_ty: self.cast_ty,
});
}
// Chalk doesn't support trait upcasting and fails to solve some obvious goals
// when the trait environment contains some recursive traits (See issue #18047)
// We skip cast checks for such cases for now, until the next-gen solver.
- if contains_dyn_trait(&self.cast_ty) {
+ if contains_dyn_trait(self.cast_ty) {
return Ok(());
}
- self.do_check(ctx)
- .map_err(|e| e.into_diagnostic(self.expr, self.expr_ty.clone(), self.cast_ty.clone()))
+ self.do_check(ctx).map_err(|e| e.into_diagnostic(self.expr, self.expr_ty, self.cast_ty))
}
- fn do_check(&self, ctx: &mut InferenceContext<'_>) -> Result<(), CastError> {
- let (t_from, t_cast) = match (
- CastTy::from_ty(ctx.db, &self.expr_ty),
- CastTy::from_ty(ctx.db, &self.cast_ty),
- ) {
- (Some(t_from), Some(t_cast)) => (t_from, t_cast),
- (None, Some(t_cast)) => match self.expr_ty.kind(Interner) {
- TyKind::FnDef(..) => {
- let sig = self.expr_ty.callable_sig(ctx.db).expect("FnDef had no sig");
- let sig = ctx.table.eagerly_normalize_and_resolve_shallow_in(sig);
- let fn_ptr = TyKind::Function(sig.to_fn_ptr()).intern(Interner);
- if ctx
- .coerce(
- self.source_expr.into(),
- self.expr_ty.to_nextsolver(ctx.table.interner),
- fn_ptr.to_nextsolver(ctx.table.interner),
- AllowTwoPhase::No,
- CoerceNever::Yes,
- )
- .is_ok()
- {
- } else {
- return Err(CastError::IllegalCast);
- }
+ fn do_check(&self, ctx: &mut InferenceContext<'_, 'db>) -> Result<(), CastError> {
+ let (t_from, t_cast) =
+ match (CastTy::from_ty(ctx.db, self.expr_ty), CastTy::from_ty(ctx.db, self.cast_ty)) {
+ (Some(t_from), Some(t_cast)) => (t_from, t_cast),
+ (None, Some(t_cast)) => match self.expr_ty.kind() {
+ TyKind::FnDef(..) => {
+ let sig =
+ self.expr_ty.callable_sig(ctx.interner()).expect("FnDef had no sig");
+ let sig = ctx.table.eagerly_normalize_and_resolve_shallow_in(sig);
+ let fn_ptr = Ty::new_fn_ptr(ctx.interner(), sig);
+ if ctx
+ .coerce(
+ self.source_expr.into(),
+ self.expr_ty,
+ fn_ptr,
+ AllowTwoPhase::No,
+ CoerceNever::Yes,
+ )
+ .is_ok()
+ {
+ } else {
+ return Err(CastError::IllegalCast);
+ }
- (CastTy::FnPtr, t_cast)
- }
- TyKind::Ref(mutbl, _, inner_ty) => {
- return match t_cast {
- CastTy::Int(_) | CastTy::Float => match inner_ty.kind(Interner) {
- TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_))
- | TyKind::InferenceVar(
- _,
- TyVariableKind::Integer | TyVariableKind::Float,
- ) => Err(CastError::NeedDeref),
-
- _ => Err(CastError::NeedViaPtr),
- },
- // array-ptr-cast
- CastTy::Ptr(t, m) => {
- let t = ctx.table.eagerly_normalize_and_resolve_shallow_in(t);
- if !ctx.table.is_sized(&t) {
- return Err(CastError::IllegalCast);
+ (CastTy::FnPtr, t_cast)
+ }
+ TyKind::Ref(_, inner_ty, mutbl) => {
+ return match t_cast {
+ CastTy::Int(_) | CastTy::Float => match inner_ty.kind() {
+ TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
+ | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => {
+ Err(CastError::NeedDeref)
+ }
+
+ _ => Err(CastError::NeedViaPtr),
+ },
+ // array-ptr-cast
+ CastTy::Ptr(t, m) => {
+ let t = ctx.table.eagerly_normalize_and_resolve_shallow_in(t);
+ if !ctx.table.is_sized(t) {
+ return Err(CastError::IllegalCast);
+ }
+ self.check_ref_cast(ctx, inner_ty, mutbl, t, m)
}
- self.check_ref_cast(ctx, inner_ty, *mutbl, &t, m)
- }
- _ => Err(CastError::NonScalar),
- };
- }
+ _ => Err(CastError::NonScalar),
+ };
+ }
+ _ => return Err(CastError::NonScalar),
+ },
_ => return Err(CastError::NonScalar),
- },
- _ => return Err(CastError::NonScalar),
- };
+ };
// rustc checks whether the `expr_ty` is foreign adt with `non_exhaustive` sym
@@ -207,10 +217,10 @@ impl CastCheck {
}
(CastTy::Int(Int::Bool | Int::CEnum | Int::Char) | CastTy::Float, CastTy::Ptr(..))
| (CastTy::Ptr(..) | CastTy::FnPtr, CastTy::Float) => Err(CastError::IllegalCast),
- (CastTy::Ptr(src, _), CastTy::Ptr(dst, _)) => self.check_ptr_ptr_cast(ctx, &src, &dst),
- (CastTy::Ptr(src, _), CastTy::Int(_)) => self.check_ptr_addr_cast(ctx, &src),
- (CastTy::Int(_), CastTy::Ptr(dst, _)) => self.check_addr_ptr_cast(ctx, &dst),
- (CastTy::FnPtr, CastTy::Ptr(dst, _)) => self.check_fptr_ptr_cast(ctx, &dst),
+ (CastTy::Ptr(src, _), CastTy::Ptr(dst, _)) => self.check_ptr_ptr_cast(ctx, src, dst),
+ (CastTy::Ptr(src, _), CastTy::Int(_)) => self.check_ptr_addr_cast(ctx, src),
+ (CastTy::Int(_), CastTy::Ptr(dst, _)) => self.check_addr_ptr_cast(ctx, dst),
+ (CastTy::FnPtr, CastTy::Ptr(dst, _)) => self.check_fptr_ptr_cast(ctx, dst),
(CastTy::Int(Int::CEnum), CastTy::Int(_)) => Ok(()),
(CastTy::Int(Int::Char | Int::Bool), CastTy::Int(_)) => Ok(()),
(CastTy::Int(_) | CastTy::Float, CastTy::Int(_) | CastTy::Float) => Ok(()),
@@ -220,23 +230,23 @@ impl CastCheck {
fn check_ref_cast(
&self,
- ctx: &mut InferenceContext<'_>,
- t_expr: &Ty,
+ ctx: &mut InferenceContext<'_, 'db>,
+ t_expr: Ty<'db>,
m_expr: Mutability,
- t_cast: &Ty,
+ t_cast: Ty<'db>,
m_cast: Mutability,
) -> Result<(), CastError> {
// Mutability order is opposite to rustc. `Mut < Not`
if m_expr <= m_cast
- && let TyKind::Array(ety, _) = t_expr.kind(Interner)
+ && let TyKind::Array(ety, _) = t_expr.kind()
{
// Coerce to a raw pointer so that we generate RawPtr in MIR.
- let array_ptr_type = TyKind::Raw(m_expr, t_expr.clone()).intern(Interner);
+ let array_ptr_type = Ty::new_ptr(ctx.interner(), t_expr, m_expr);
if ctx
.coerce(
self.source_expr.into(),
- self.expr_ty.to_nextsolver(ctx.table.interner),
- array_ptr_type.to_nextsolver(ctx.table.interner),
+ self.expr_ty,
+ array_ptr_type,
AllowTwoPhase::No,
CoerceNever::Yes,
)
@@ -253,13 +263,7 @@ impl CastCheck {
// This is a less strict condition than rustc's `demand_eqtype`,
// but false negative is better than false positive
if ctx
- .coerce(
- self.source_expr.into(),
- ety.to_nextsolver(ctx.table.interner),
- t_cast.to_nextsolver(ctx.table.interner),
- AllowTwoPhase::No,
- CoerceNever::Yes,
- )
+ .coerce(self.source_expr.into(), ety, t_cast, AllowTwoPhase::No, CoerceNever::Yes)
.is_ok()
{
return Ok(());
@@ -271,9 +275,9 @@ impl CastCheck {
fn check_ptr_ptr_cast(
&self,
- ctx: &mut InferenceContext<'_>,
- src: &Ty,
- dst: &Ty,
+ ctx: &mut InferenceContext<'_, 'db>,
+ src: Ty<'db>,
+ dst: Ty<'db>,
) -> Result<(), CastError> {
let src_kind = pointer_kind(src, ctx).map_err(|_| CastError::Unknown)?;
let dst_kind = pointer_kind(dst, ctx).map_err(|_| CastError::Unknown)?;
@@ -286,24 +290,13 @@ impl CastCheck {
(_, Some(PointerKind::Thin)) => Ok(()),
(Some(PointerKind::Thin), _) => Err(CastError::SizedUnsizedCast),
(Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => {
- let principal = |tty: &Binders<QuantifiedWhereClauses>| {
- tty.skip_binders().as_slice(Interner).first().and_then(|pred| {
- if let WhereClause::Implemented(tr) = pred.skip_binders() {
- Some(tr.trait_id)
- } else {
- None
- }
- })
- };
- match (principal(&src_tty), principal(&dst_tty)) {
+ match (src_tty.principal_def_id(), dst_tty.principal_def_id()) {
(Some(src_principal), Some(dst_principal)) => {
if src_principal == dst_principal {
return Ok(());
}
- let src_principal =
- ctx.db.trait_signature(from_chalk_trait_id(src_principal));
- let dst_principal =
- ctx.db.trait_signature(from_chalk_trait_id(dst_principal));
+ let src_principal = ctx.db.trait_signature(src_principal.0);
+ let dst_principal = ctx.db.trait_signature(dst_principal.0);
if src_principal.flags.contains(TraitFlags::AUTO)
&& dst_principal.flags.contains(TraitFlags::AUTO)
{
@@ -322,8 +315,8 @@ impl CastCheck {
fn check_ptr_addr_cast(
&self,
- ctx: &mut InferenceContext<'_>,
- expr_ty: &Ty,
+ ctx: &mut InferenceContext<'_, 'db>,
+ expr_ty: Ty<'db>,
) -> Result<(), CastError> {
match pointer_kind(expr_ty, ctx).map_err(|_| CastError::Unknown)? {
// None => Err(CastError::UnknownExprPtrKind),
@@ -336,8 +329,8 @@ impl CastCheck {
fn check_addr_ptr_cast(
&self,
- ctx: &mut InferenceContext<'_>,
- cast_ty: &Ty,
+ ctx: &mut InferenceContext<'_, 'db>,
+ cast_ty: Ty<'db>,
) -> Result<(), CastError> {
match pointer_kind(cast_ty, ctx).map_err(|_| CastError::Unknown)? {
// None => Err(CastError::UnknownCastPtrKind),
@@ -352,8 +345,8 @@ impl CastCheck {
fn check_fptr_ptr_cast(
&self,
- ctx: &mut InferenceContext<'_>,
- cast_ty: &Ty,
+ ctx: &mut InferenceContext<'_, 'db>,
+ cast_ty: Ty<'db>,
) -> Result<(), CastError> {
match pointer_kind(cast_ty, ctx).map_err(|_| CastError::Unknown)? {
// None => Err(CastError::UnknownCastPtrKind),
@@ -366,30 +359,34 @@ impl CastCheck {
}
#[derive(Debug, PartialEq, Eq)]
-enum PointerKind {
+enum PointerKind<'db> {
// thin pointer
Thin,
// trait object
- VTable(Binders<QuantifiedWhereClauses>),
+ VTable(BoundExistentialPredicates<'db>),
// slice
Length,
OfAlias,
- OfParam(PlaceholderIndex),
+ OfParam(ParamTy),
Error,
}
-fn pointer_kind(ty: &Ty, ctx: &mut InferenceContext<'_>) -> Result<Option<PointerKind>, ()> {
- let ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(ty.clone());
+fn pointer_kind<'db>(
+ ty: Ty<'db>,
+ ctx: &mut InferenceContext<'_, 'db>,
+) -> Result<Option<PointerKind<'db>>, ()> {
+ let ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(ty);
- if ctx.table.is_sized(&ty) {
+ if ctx.table.is_sized(ty) {
return Ok(Some(PointerKind::Thin));
}
- match ty.kind(Interner) {
+ match ty.kind() {
TyKind::Slice(_) | TyKind::Str => Ok(Some(PointerKind::Length)),
- TyKind::Dyn(DynTy { bounds, .. }) => Ok(Some(PointerKind::VTable(bounds.clone()))),
- TyKind::Adt(chalk_ir::AdtId(id), subst) => {
- let AdtId::StructId(id) = *id else {
+ TyKind::Dynamic(bounds, _) => Ok(Some(PointerKind::VTable(bounds))),
+ TyKind::Adt(adt_def, subst) => {
+ let id = adt_def.def_id().0;
+ let AdtId::StructId(id) = id else {
never!("`{:?}` should be sized but is not?", ty);
return Err(());
};
@@ -397,69 +394,63 @@ fn pointer_kind(ty: &Ty, ctx: &mut InferenceContext<'_>) -> Result<Option<Pointe
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(id.into())[last_field].clone().substitute(Interner, subst);
- pointer_kind(&last_field_ty, ctx)
+ ctx.db.field_types_ns(id.into())[last_field].instantiate(ctx.interner(), subst);
+ pointer_kind(last_field_ty, ctx)
} else {
Ok(Some(PointerKind::Thin))
}
}
- TyKind::Tuple(_, subst) => {
- match subst.iter(Interner).last().and_then(|arg| arg.ty(Interner)) {
- None => Ok(Some(PointerKind::Thin)),
- Some(ty) => pointer_kind(ty, ctx),
- }
- }
+ TyKind::Tuple(subst) => match subst.iter().last() {
+ None => Ok(Some(PointerKind::Thin)),
+ Some(ty) => pointer_kind(ty, ctx),
+ },
TyKind::Foreign(_) => Ok(Some(PointerKind::Thin)),
- TyKind::Alias(_) | TyKind::AssociatedType(..) | TyKind::OpaqueType(..) => {
- Ok(Some(PointerKind::OfAlias))
- }
- TyKind::Error => Ok(Some(PointerKind::Error)),
- TyKind::Placeholder(idx) => Ok(Some(PointerKind::OfParam(*idx))),
- TyKind::BoundVar(_) | TyKind::InferenceVar(..) => Ok(None),
- TyKind::Scalar(_)
+ TyKind::Alias(..) => Ok(Some(PointerKind::OfAlias)),
+ TyKind::Error(_) => Ok(Some(PointerKind::Error)),
+ TyKind::Param(idx) => Ok(Some(PointerKind::OfParam(idx))),
+ TyKind::Bound(..) | TyKind::Placeholder(..) | TyKind::Infer(..) => Ok(None),
+ TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
+ | TyKind::Bool
+ | TyKind::Char
| TyKind::Array(..)
| TyKind::CoroutineWitness(..)
- | TyKind::Raw(..)
+ | TyKind::RawPtr(..)
| TyKind::Ref(..)
| TyKind::FnDef(..)
- | TyKind::Function(_)
+ | TyKind::FnPtr(..)
| TyKind::Closure(..)
| TyKind::Coroutine(..)
+ | TyKind::CoroutineClosure(..)
| TyKind::Never => {
never!("`{:?}` should be sized but is not?", ty);
Err(())
}
+ TyKind::UnsafeBinder(..) | TyKind::Pat(..) => {
+ never!("we don't produce these types: {ty:?}");
+ Err(())
+ }
}
}
-fn contains_dyn_trait(ty: &Ty) -> bool {
+fn contains_dyn_trait<'db>(ty: Ty<'db>) -> bool {
use std::ops::ControlFlow;
- use chalk_ir::{
- DebruijnIndex,
- visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
- };
+ use rustc_type_ir::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
struct DynTraitVisitor;
- impl TypeVisitor<Interner> for DynTraitVisitor {
- type BreakTy = ();
-
- fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
+ impl<'db> TypeVisitor<DbInterner<'db>> for DynTraitVisitor {
+ type Result = ControlFlow<()>;
- fn visit_ty(&mut self, ty: &Ty, outer_binder: DebruijnIndex) -> ControlFlow<Self::BreakTy> {
- match ty.kind(Interner) {
- TyKind::Dyn(_) => ControlFlow::Break(()),
- _ => ty.super_visit_with(self.as_dyn(), outer_binder),
+ fn visit_ty(&mut self, ty: Ty<'db>) -> ControlFlow<()> {
+ match ty.kind() {
+ TyKind::Dynamic(..) => ControlFlow::Break(()),
+ _ => ty.super_visit_with(self),
}
}
}
- ty.visit_with(DynTraitVisitor.as_dyn(), DebruijnIndex::INNERMOST).is_break()
+ ty.visit_with(&mut DynTraitVisitor).is_break()
}
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 4a57b2f375..2637ed6b3e 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -2,8 +2,7 @@
pub(crate) mod analysis;
-use std::ops::ControlFlow;
-use std::{iter, mem};
+use std::{iter, mem, ops::ControlFlow};
use hir_def::{
TraitId,
@@ -18,7 +17,6 @@ use rustc_type_ir::{
};
use tracing::debug;
-use crate::traits::FnTrait;
use crate::{
FnAbi,
db::{InternedClosure, InternedCoroutine},
@@ -31,25 +29,25 @@ use crate::{
BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult,
traits::{ObligationCause, PredicateObligations},
},
- mapping::{ChalkToNextSolver, NextSolverToChalk},
util::explicit_item_bounds,
},
+ traits::FnTrait,
};
use super::{Expectation, InferenceContext};
#[derive(Debug)]
-struct ClosureSignatures<'tcx> {
+struct ClosureSignatures<'db> {
/// The signature users of the closure see.
- bound_sig: PolyFnSig<'tcx>,
+ bound_sig: PolyFnSig<'db>,
/// The signature within the function body.
/// This mostly differs in the sense that lifetimes are now early bound and any
/// opaque types from the signature expectation are overridden in case there are
/// explicit hidden types written by the user in the closure signature.
- liberated_sig: FnSig<'tcx>,
+ liberated_sig: FnSig<'db>,
}
-impl<'db> InferenceContext<'db> {
+impl<'db> InferenceContext<'_, 'db> {
pub(super) fn infer_closure(
&mut self,
body: ExprId,
@@ -58,15 +56,13 @@ impl<'db> InferenceContext<'db> {
arg_types: &[Option<TypeRefId>],
closure_kind: ClosureKind,
tgt_expr: ExprId,
- expected: &Expectation,
- ) -> crate::Ty {
+ expected: &Expectation<'db>,
+ ) -> Ty<'db> {
assert_eq!(args.len(), arg_types.len());
- let interner = self.table.interner;
+ let interner = self.interner();
let (expected_sig, expected_kind) = match expected.to_option(&mut self.table) {
- Some(expected_ty) => {
- self.deduce_closure_signature(expected_ty.to_nextsolver(interner), closure_kind)
- }
+ Some(expected_ty) => self.deduce_closure_signature(expected_ty, closure_kind),
None => (None, None),
};
@@ -79,10 +75,7 @@ impl<'db> InferenceContext<'db> {
let (id, ty, resume_yield_tys) = match closure_kind {
ClosureKind::Coroutine(_) => {
let yield_ty = self.table.next_ty_var();
- let resume_ty = liberated_sig
- .inputs()
- .get(0)
- .unwrap_or(self.result.standard_types.unit.to_nextsolver(interner));
+ let resume_ty = liberated_sig.inputs().get(0).unwrap_or(self.types.unit);
// FIXME: Infer the upvars later.
let parts = CoroutineArgsParts {
@@ -102,11 +95,7 @@ impl<'db> InferenceContext<'db> {
CoroutineArgs::new(interner, parts).args,
);
- (
- None,
- coroutine_ty,
- Some((resume_ty.to_chalk(interner), yield_ty.to_chalk(interner))),
- )
+ (None, coroutine_ty, Some((resume_ty, yield_ty)))
}
// FIXME(next-solver): `ClosureKind::Async` should really be a separate arm that creates a `CoroutineClosure`.
// But for now we treat it as a closure.
@@ -115,7 +104,7 @@ impl<'db> InferenceContext<'db> {
match expected_kind {
Some(kind) => {
self.result.closure_info.insert(
- closure_id.into(),
+ closure_id,
(
Vec::new(),
match kind {
@@ -151,13 +140,13 @@ impl<'db> InferenceContext<'db> {
// Now go through the argument patterns
for (arg_pat, arg_ty) in args.iter().zip(bound_sig.skip_binder().inputs()) {
- self.infer_top_pat(*arg_pat, &arg_ty.to_chalk(interner), None);
+ self.infer_top_pat(*arg_pat, arg_ty, None);
}
// FIXME: lift these out into a struct
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let prev_closure = mem::replace(&mut self.current_closure, id);
- let prev_ret_ty = mem::replace(&mut self.return_ty, body_ret_ty.to_chalk(interner));
+ let prev_ret_ty = mem::replace(&mut self.return_ty, body_ret_ty);
let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(body_ret_ty));
let prev_resume_yield_tys = mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
@@ -171,7 +160,7 @@ impl<'db> InferenceContext<'db> {
self.current_closure = prev_closure;
self.resume_yield_tys = prev_resume_yield_tys;
- ty.to_chalk(interner)
+ ty
}
fn fn_trait_kind_from_def_id(&self, trait_id: TraitId) -> Option<rustc_type_ir::ClosureKind> {
@@ -209,14 +198,13 @@ impl<'db> InferenceContext<'db> {
.deduce_closure_signature_from_predicates(
expected_ty,
closure_kind,
- explicit_item_bounds(self.table.interner, def_id)
- .iter_instantiated(self.table.interner, args)
+ explicit_item_bounds(self.interner(), def_id)
+ .iter_instantiated(self.interner(), args)
.map(|clause| clause.as_predicate()),
),
TyKind::Dynamic(object_type, ..) => {
let sig = object_type.projection_bounds().into_iter().find_map(|pb| {
- let pb =
- pb.with_self_ty(self.table.interner, Ty::new_unit(self.table.interner));
+ let pb = pb.with_self_ty(self.interner(), Ty::new_unit(self.interner()));
self.deduce_sig_from_projection(closure_kind, pb)
});
let kind = object_type
@@ -226,7 +214,7 @@ impl<'db> InferenceContext<'db> {
}
TyKind::Infer(rustc_type_ir::TyVar(vid)) => self
.deduce_closure_signature_from_predicates(
- Ty::new_var(self.table.interner, self.table.infer_ctxt.root_var(vid)),
+ Ty::new_var(self.interner(), self.table.infer_ctxt.root_var(vid)),
closure_kind,
self.table.obligations_for_self_ty(vid).into_iter().map(|obl| obl.predicate),
),
@@ -251,7 +239,7 @@ impl<'db> InferenceContext<'db> {
let mut expected_kind = None;
for pred in rustc_type_ir::elaborate::elaborate(
- self.table.interner,
+ self.interner(),
// Reverse the obligations here, since `elaborate_*` uses a stack,
// and we want to keep inference generally in the same order of
// the registered obligations.
@@ -313,7 +301,7 @@ impl<'db> InferenceContext<'db> {
// even though the normalized form may not name `expected_ty`. However, this matches the existing
// behaviour of the old solver and would be technically a breaking change to fix.
let generalized_fnptr_sig = self.table.next_ty_var();
- let inferred_fnptr_sig = Ty::new_fn_ptr(self.table.interner, inferred_sig);
+ let inferred_fnptr_sig = Ty::new_fn_ptr(self.interner(), inferred_sig);
// FIXME: Report diagnostics.
_ = self
.table
@@ -326,7 +314,7 @@ impl<'db> InferenceContext<'db> {
self.table.infer_ctxt.resolve_vars_if_possible(generalized_fnptr_sig);
if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
- expected_sig = Some(resolved_sig.fn_sig(self.table.interner));
+ expected_sig = Some(resolved_sig.fn_sig(self.interner()));
}
} else if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
expected_sig = inferred_sig;
@@ -339,7 +327,7 @@ impl<'db> InferenceContext<'db> {
// many viable options, so pick the most restrictive.
let trait_def_id = match bound_predicate.skip_binder() {
PredicateKind::Clause(ClauseKind::Projection(data)) => {
- Some(data.projection_term.trait_def_id(self.table.interner).0)
+ Some(data.projection_term.trait_def_id(self.interner()).0)
}
PredicateKind::Clause(ClauseKind::Trait(data)) => Some(data.def_id().0),
_ => None,
@@ -427,7 +415,7 @@ impl<'db> InferenceContext<'db> {
let ret_param_ty = projection.skip_binder().term.expect_type();
debug!(?ret_param_ty);
- let sig = projection.rebind(self.table.interner.mk_fn_sig(
+ let sig = projection.rebind(self.interner().mk_fn_sig(
input_tys,
ret_param_ty,
false,
@@ -515,7 +503,7 @@ impl<'db> InferenceContext<'db> {
// that does not misuse a `FnSig` type, but that can be done separately.
let return_ty = return_ty.unwrap_or_else(|| self.table.next_ty_var());
- let sig = projection.rebind(self.table.interner.mk_fn_sig(
+ let sig = projection.rebind(self.interner().mk_fn_sig(
input_tys,
return_ty,
false,
@@ -619,7 +607,7 @@ impl<'db> InferenceContext<'db> {
// in this binder we are creating.
assert!(!expected_sig.skip_binder().has_vars_bound_above(rustc_type_ir::INNERMOST));
let bound_sig = expected_sig.map_bound(|sig| {
- self.table.interner.mk_fn_sig(
+ self.interner().mk_fn_sig(
sig.inputs(),
sig.output(),
sig.c_variadic,
@@ -631,7 +619,7 @@ impl<'db> InferenceContext<'db> {
// `deduce_expectations_from_expected_type` introduces
// late-bound lifetimes defined elsewhere, which we now
// anonymize away, so as not to confuse the user.
- let bound_sig = self.table.interner.anonymize_bound_vars(bound_sig);
+ let bound_sig = self.interner().anonymize_bound_vars(bound_sig);
let closure_sigs = self.closure_sigs(bound_sig);
@@ -723,7 +711,7 @@ impl<'db> InferenceContext<'db> {
.into_iter()
.map(|ty| table.infer_ctxt.resolve_vars_if_possible(ty));
- expected_sigs.liberated_sig = table.interner.mk_fn_sig(
+ expected_sigs.liberated_sig = table.interner().mk_fn_sig(
inputs,
supplied_output_ty,
expected_sigs.liberated_sig.c_variadic,
@@ -744,12 +732,12 @@ impl<'db> InferenceContext<'db> {
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
) -> PolyFnSig<'db> {
- let interner = self.table.interner;
+ let interner = self.interner();
let supplied_return = match decl_output {
Some(output) => {
let output = self.make_body_ty(output);
- self.process_user_written_ty(output).to_nextsolver(interner)
+ self.process_user_written_ty(output)
}
None => self.table.next_ty_var(),
};
@@ -757,7 +745,7 @@ impl<'db> InferenceContext<'db> {
let supplied_arguments = decl_inputs.iter().map(|&input| match input {
Some(input) => {
let input = self.make_body_ty(input);
- self.process_user_written_ty(input).to_nextsolver(interner)
+ self.process_user_written_ty(input)
}
None => self.table.next_ty_var(),
});
@@ -779,7 +767,7 @@ impl<'db> InferenceContext<'db> {
decl_inputs: &[Option<TypeRefId>],
decl_output: Option<TypeRefId>,
) -> PolyFnSig<'db> {
- let interner = self.table.interner;
+ let interner = self.interner();
let err_ty = Ty::new_error(interner, ErrorGuaranteed);
if let Some(output) = decl_output {
diff --git a/crates/hir-ty/src/infer/closure/analysis.rs b/crates/hir-ty/src/infer/closure/analysis.rs
index fd14b9e2de..8a6ce0a69b 100644
--- a/crates/hir-ty/src/infer/closure/analysis.rs
+++ b/crates/hir-ty/src/infer/closure/analysis.rs
@@ -2,10 +2,6 @@
use std::{cmp, convert::Infallible, mem};
-use chalk_ir::{
- BoundVar, DebruijnIndex, Mutability, TyKind,
- fold::{FallibleTypeFolder, TypeFoldable},
-};
use either::Either;
use hir_def::{
DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId,
@@ -20,44 +16,47 @@ use hir_def::{
};
use hir_expand::name::Name;
use intern::sym;
+use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_type_ir::inherent::{IntoKind, SliceLike, Ty as _};
use smallvec::{SmallVec, smallvec};
use stdx::{format_to, never};
use syntax::utils::is_raw_identifier;
-use crate::db::InternedClosureId;
-use crate::infer::InferenceContext;
use crate::{
- Adjust, Adjustment, Binders, BindingMode, ClosureId, Interner, Substitution, Ty, TyExt,
- db::{HirDatabase, InternedClosure},
- error_lifetime, from_placeholder_idx,
- generics::Generics,
- make_binders,
+ Adjust, Adjustment, BindingMode,
+ db::{HirDatabase, InternedClosure, InternedClosureId},
+ infer::InferenceContext,
mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
+ next_solver::{
+ DbInterner, EarlyBinder, GenericArgs, Ty, TyKind,
+ mapping::{ChalkToNextSolver, NextSolverToChalk},
+ },
traits::FnTrait,
- utils,
};
// The below functions handle capture and closure kind (Fn, FnMut, ..)
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub(crate) struct HirPlace {
+pub(crate) struct HirPlace<'db> {
pub(crate) local: BindingId,
- pub(crate) projections: Vec<ProjectionElem<Infallible, Ty>>,
+ pub(crate) projections: Vec<ProjectionElem<Infallible, Ty<'db>>>,
}
-impl HirPlace {
- fn ty(&self, ctx: &mut InferenceContext<'_>) -> Ty {
- let mut ty = ctx.table.resolve_completely(ctx.result[self.local].clone());
+impl<'db> HirPlace<'db> {
+ fn ty(&self, ctx: &mut InferenceContext<'_, 'db>) -> Ty<'db> {
+ let mut ty = ctx.table.resolve_completely(ctx.result[self.local]);
for p in &self.projections {
- ty = p.projected_ty(
- ty,
- ctx.db,
- |_, _, _| {
- unreachable!("Closure field only happens in MIR");
- },
- ctx.owner.module(ctx.db).krate(),
- );
+ ty = p
+ .projected_ty(
+ ty.to_chalk(ctx.interner()),
+ ctx.db,
+ |_, _, _| {
+ unreachable!("Closure field only happens in MIR");
+ },
+ ctx.owner.module(ctx.db).krate(),
+ )
+ .to_nextsolver(ctx.interner());
}
ty
}
@@ -86,8 +85,8 @@ pub enum CaptureKind {
}
#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct CapturedItem {
- pub(crate) place: HirPlace,
+pub struct CapturedItem<'db> {
+ pub(crate) place: HirPlace<'db>,
pub(crate) kind: CaptureKind,
/// The inner vec is the stacks; the outer vec is for each capture reference.
///
@@ -96,10 +95,10 @@ pub struct CapturedItem {
/// copy all captures of the inner closure to the outer closure, and then we may
/// truncate them, and we want the correct span to be reported.
span_stacks: SmallVec<[SmallVec<[MirSpan; 3]>; 3]>,
- pub(crate) ty: Binders<Ty>,
+ pub(crate) ty: EarlyBinder<'db, Ty<'db>>,
}
-impl CapturedItem {
+impl<'db> CapturedItem<'db> {
pub fn local(&self) -> BindingId {
self.place.local
}
@@ -109,8 +108,9 @@ impl CapturedItem {
self.place.projections.iter().any(|it| !matches!(it, ProjectionElem::Deref))
}
- pub fn ty(&self, db: &dyn HirDatabase, subst: &Substitution) -> Ty {
- self.ty.clone().substitute(Interner, &utils::ClosureSubst(subst).parent_subst(db))
+ pub fn ty(&self, db: &'db dyn HirDatabase, subst: GenericArgs<'db>) -> Ty<'db> {
+ let interner = DbInterner::new_with(db, None, None);
+ self.ty.instantiate(interner, subst.split_closure_args_untupled().parent_args)
}
pub fn kind(&self) -> CaptureKind {
@@ -279,15 +279,15 @@ impl CapturedItem {
}
#[derive(Debug, Clone, PartialEq, Eq)]
-pub(crate) struct CapturedItemWithoutTy {
- pub(crate) place: HirPlace,
+pub(crate) struct CapturedItemWithoutTy<'db> {
+ pub(crate) place: HirPlace<'db>,
pub(crate) kind: CaptureKind,
/// The inner vec is the stacks; the outer vec is for each capture reference.
pub(crate) span_stacks: SmallVec<[SmallVec<[MirSpan; 3]>; 3]>,
}
-impl CapturedItemWithoutTy {
- fn with_ty(self, ctx: &mut InferenceContext<'_>) -> CapturedItem {
+impl<'db> CapturedItemWithoutTy<'db> {
+ fn with_ty(self, ctx: &mut InferenceContext<'_, 'db>) -> CapturedItem<'db> {
let ty = self.place.ty(ctx);
let ty = match &self.kind {
CaptureKind::ByValue => ty,
@@ -296,66 +296,20 @@ impl CapturedItemWithoutTy {
BorrowKind::Mut { .. } => Mutability::Mut,
_ => Mutability::Not,
};
- TyKind::Ref(m, error_lifetime(), ty).intern(Interner)
+ Ty::new_ref(ctx.interner(), ctx.types.re_error, ty, m)
}
};
- return CapturedItem {
+ CapturedItem {
place: self.place,
kind: self.kind,
span_stacks: self.span_stacks,
- ty: replace_placeholder_with_binder(ctx, ty),
- };
-
- fn replace_placeholder_with_binder(ctx: &mut InferenceContext<'_>, ty: Ty) -> Binders<Ty> {
- struct Filler<'a> {
- db: &'a dyn HirDatabase,
- generics: &'a Generics,
- }
- impl FallibleTypeFolder<Interner> for Filler<'_> {
- type Error = ();
-
- fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
-
- fn try_fold_free_placeholder_const(
- &mut self,
- ty: chalk_ir::Ty<Interner>,
- idx: chalk_ir::PlaceholderIndex,
- outer_binder: DebruijnIndex,
- ) -> Result<chalk_ir::Const<Interner>, Self::Error> {
- let x = from_placeholder_idx(self.db, idx).0;
- let Some(idx) = self.generics.type_or_const_param_idx(x) else {
- return Err(());
- };
- Ok(BoundVar::new(outer_binder, idx).to_const(Interner, ty))
- }
-
- fn try_fold_free_placeholder_ty(
- &mut self,
- idx: chalk_ir::PlaceholderIndex,
- outer_binder: DebruijnIndex,
- ) -> std::result::Result<Ty, Self::Error> {
- let x = from_placeholder_idx(self.db, idx).0;
- let Some(idx) = self.generics.type_or_const_param_idx(x) else {
- return Err(());
- };
- Ok(BoundVar::new(outer_binder, idx).to_ty(Interner))
- }
- }
- let filler = &mut Filler { db: ctx.db, generics: ctx.generics() };
- let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty);
- make_binders(ctx.db, filler.generics, result)
+ ty: EarlyBinder::bind(ty),
}
}
}
-impl InferenceContext<'_> {
- fn place_of_expr(&mut self, tgt_expr: ExprId) -> Option<HirPlace> {
+impl<'db> InferenceContext<'_, 'db> {
+ fn place_of_expr(&mut self, tgt_expr: ExprId) -> Option<HirPlace<'db>> {
let r = self.place_of_expr_without_adjust(tgt_expr)?;
let adjustments =
self.result.expr_adjustments.get(&tgt_expr).map(|it| &**it).unwrap_or_default();
@@ -363,7 +317,7 @@ impl InferenceContext<'_> {
}
/// Pushes the span into `current_capture_span_stack`, *without clearing it first*.
- fn path_place(&mut self, path: &Path, id: ExprOrPatId) -> Option<HirPlace> {
+ fn path_place(&mut self, path: &Path, id: ExprOrPatId) -> Option<HirPlace<'db>> {
if path.type_anchor().is_some() {
return None;
}
@@ -384,7 +338,7 @@ impl InferenceContext<'_> {
}
/// Changes `current_capture_span_stack` to contain the stack of spans for this expr.
- fn place_of_expr_without_adjust(&mut self, tgt_expr: ExprId) -> Option<HirPlace> {
+ fn place_of_expr_without_adjust(&mut self, tgt_expr: ExprId) -> Option<HirPlace<'db>> {
self.current_capture_span_stack.clear();
match &self.body[tgt_expr] {
Expr::Path(p) => {
@@ -403,8 +357,8 @@ impl InferenceContext<'_> {
}
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
if matches!(
- self.expr_ty_after_adjustments(*expr).kind(Interner),
- TyKind::Ref(..) | TyKind::Raw(..)
+ self.expr_ty_after_adjustments(*expr).kind(),
+ TyKind::Ref(..) | TyKind::RawPtr(..)
) {
let mut place = self.place_of_expr(*expr)?;
self.current_capture_span_stack.push(MirSpan::ExprId(tgt_expr));
@@ -417,7 +371,7 @@ impl InferenceContext<'_> {
None
}
- fn push_capture(&mut self, place: HirPlace, kind: CaptureKind) {
+ fn push_capture(&mut self, place: HirPlace<'db>, kind: CaptureKind) {
self.current_captures.push(CapturedItemWithoutTy {
place,
kind,
@@ -425,7 +379,11 @@ impl InferenceContext<'_> {
});
}
- fn truncate_capture_spans(&self, capture: &mut CapturedItemWithoutTy, mut truncate_to: usize) {
+ fn truncate_capture_spans(
+ &self,
+ capture: &mut CapturedItemWithoutTy<'db>,
+ mut truncate_to: usize,
+ ) {
// The first span is the identifier, and it must always remain.
truncate_to += 1;
for span_stack in &mut capture.span_stacks {
@@ -450,14 +408,14 @@ impl InferenceContext<'_> {
}
}
- fn ref_expr(&mut self, expr: ExprId, place: Option<HirPlace>) {
+ fn ref_expr(&mut self, expr: ExprId, place: Option<HirPlace<'db>>) {
if let Some(place) = place {
self.add_capture(place, CaptureKind::ByRef(BorrowKind::Shared));
}
self.walk_expr(expr);
}
- fn add_capture(&mut self, place: HirPlace, kind: CaptureKind) {
+ fn add_capture(&mut self, place: HirPlace<'db>, kind: CaptureKind) {
if self.is_upvar(&place) {
self.push_capture(place, kind);
}
@@ -473,7 +431,7 @@ impl InferenceContext<'_> {
}
}
- fn mutate_expr(&mut self, expr: ExprId, place: Option<HirPlace>) {
+ fn mutate_expr(&mut self, expr: ExprId, place: Option<HirPlace<'db>>) {
if let Some(place) = place {
self.add_capture(
place,
@@ -490,7 +448,7 @@ impl InferenceContext<'_> {
self.walk_expr(expr);
}
- fn consume_place(&mut self, place: HirPlace) {
+ fn consume_place(&mut self, place: HirPlace<'db>) {
if self.is_upvar(&place) {
let ty = place.ty(self);
let kind = if self.is_ty_copy(ty) {
@@ -502,7 +460,7 @@ impl InferenceContext<'_> {
}
}
- fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment]) {
+ fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment<'db>]) {
if let Some((last, rest)) = adjustment.split_last() {
match &last.kind {
Adjust::NeverToAny | Adjust::Deref(None) | Adjust::Pointer(_) => {
@@ -523,7 +481,12 @@ impl InferenceContext<'_> {
}
}
- fn ref_capture_with_adjusts(&mut self, m: Mutability, tgt_expr: ExprId, rest: &[Adjustment]) {
+ fn ref_capture_with_adjusts(
+ &mut self,
+ m: Mutability,
+ tgt_expr: ExprId,
+ rest: &[Adjustment<'db>],
+ ) {
let capture_kind = match m {
Mutability::Mut => CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::Default }),
Mutability::Not => CaptureKind::ByRef(BorrowKind::Shared),
@@ -652,8 +615,8 @@ impl InferenceContext<'_> {
Expr::Field { expr, name: _ } => self.select_from_expr(*expr),
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
if matches!(
- self.expr_ty_after_adjustments(*expr).kind(Interner),
- TyKind::Ref(..) | TyKind::Raw(..)
+ self.expr_ty_after_adjustments(*expr).kind(),
+ TyKind::Ref(..) | TyKind::RawPtr(..)
) {
self.select_from_expr(*expr);
} else if let Some((f, _)) = self.result.method_resolution(tgt_expr) {
@@ -728,12 +691,12 @@ impl InferenceContext<'_> {
}
Expr::Closure { .. } => {
let ty = self.expr_ty(tgt_expr);
- let TyKind::Closure(id, _) = ty.kind(Interner) else {
+ let TyKind::Closure(id, _) = ty.kind() else {
never!("closure type is always closure");
return;
};
let (captures, _) =
- self.result.closure_info.get(id).expect(
+ self.result.closure_info.get(&id.0).expect(
"We sort closures, so we should always have data for inner closures",
);
let mut cc = mem::take(&mut self.current_captures);
@@ -830,7 +793,7 @@ impl InferenceContext<'_> {
}
Pat::Bind { id, .. } => match self.result.binding_modes[p] {
crate::BindingMode::Move => {
- if self.is_ty_copy(self.result.type_of_binding[*id].clone()) {
+ if self.is_ty_copy(self.result.type_of_binding[*id]) {
update_result(CaptureKind::ByRef(BorrowKind::Shared));
} else {
update_result(CaptureKind::ByValue);
@@ -848,21 +811,21 @@ impl InferenceContext<'_> {
self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
}
- fn expr_ty(&self, expr: ExprId) -> Ty {
- self.result[expr].clone()
+ fn expr_ty(&self, expr: ExprId) -> Ty<'db> {
+ self.result[expr]
}
- fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty {
+ fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> {
let mut ty = None;
if let Some(it) = self.result.expr_adjustments.get(&e)
&& let Some(it) = it.last()
{
- ty = Some(it.target.clone());
+ ty = Some(it.target);
}
ty.unwrap_or_else(|| self.expr_ty(e))
}
- fn is_upvar(&self, place: &HirPlace) -> bool {
+ fn is_upvar(&self, place: &HirPlace<'db>) -> bool {
if let Some(c) = self.current_closure {
let InternedClosure(_, root) = self.db.lookup_intern_closure(c);
return self.body.is_binding_upvar(place.local, root);
@@ -870,14 +833,20 @@ impl InferenceContext<'_> {
false
}
- fn is_ty_copy(&mut self, ty: Ty) -> bool {
- if let TyKind::Closure(id, _) = ty.kind(Interner) {
+ fn is_ty_copy(&mut self, ty: Ty<'db>) -> bool {
+ if let TyKind::Closure(id, _) = ty.kind() {
// FIXME: We handle closure as a special case, since chalk consider every closure as copy. We
// should probably let chalk know which closures are copy, but I don't know how doing it
// without creating query cycles.
- return self.result.closure_info.get(id).map(|it| it.1 == FnTrait::Fn).unwrap_or(true);
+ return self
+ .result
+ .closure_info
+ .get(&id.0)
+ .map(|it| it.1 == FnTrait::Fn)
+ .unwrap_or(true);
}
- self.table.resolve_completely(ty).is_copy(self.db, self.owner)
+ let ty = self.table.resolve_completely(ty);
+ self.table.type_is_copy_modulo_regions(ty)
}
fn select_from_expr(&mut self, expr: ExprId) {
@@ -888,23 +857,25 @@ impl InferenceContext<'_> {
// FIXME: Borrow checker problems without this.
let mut current_captures = std::mem::take(&mut self.current_captures);
for capture in &mut current_captures {
- let mut ty = self.table.resolve_completely(self.result[capture.place.local].clone());
- if ty.as_raw_ptr().is_some() || ty.is_union() {
+ let mut ty = self.table.resolve_completely(self.result[capture.place.local]);
+ if ty.is_raw_ptr() || ty.is_union() {
capture.kind = CaptureKind::ByRef(BorrowKind::Shared);
self.truncate_capture_spans(capture, 0);
capture.place.projections.truncate(0);
continue;
}
for (i, p) in capture.place.projections.iter().enumerate() {
- ty = p.projected_ty(
- ty,
- self.db,
- |_, _, _| {
- unreachable!("Closure field only happens in MIR");
- },
- self.owner.module(self.db).krate(),
- );
- if ty.as_raw_ptr().is_some() || ty.is_union() {
+ ty = p
+ .projected_ty(
+ ty.to_chalk(self.interner()),
+ self.db,
+ |_, _, _| {
+ unreachable!("Closure field only happens in MIR");
+ },
+ self.owner.module(self.db).krate(),
+ )
+ .to_nextsolver(self.interner());
+ if ty.is_raw_ptr() || ty.is_union() {
capture.kind = CaptureKind::ByRef(BorrowKind::Shared);
self.truncate_capture_spans(capture, i + 1);
capture.place.projections.truncate(i + 1);
@@ -932,7 +903,7 @@ impl InferenceContext<'_> {
fn minimize_captures(&mut self) {
self.current_captures.sort_unstable_by_key(|it| it.place.projections.len());
- let mut hash_map = FxHashMap::<HirPlace, usize>::default();
+ let mut hash_map = FxHashMap::<HirPlace<'db>, usize>::default();
let result = mem::take(&mut self.current_captures);
for mut item in result {
let mut lookup_place = HirPlace { local: item.place.local, projections: vec![] };
@@ -967,7 +938,7 @@ impl InferenceContext<'_> {
}
}
- fn consume_with_pat(&mut self, mut place: HirPlace, tgt_pat: PatId) {
+ fn consume_with_pat(&mut self, mut place: HirPlace<'db>, tgt_pat: PatId) {
let adjustments_count =
self.result.pat_adjustments.get(&tgt_pat).map(|it| it.len()).unwrap_or_default();
place.projections.extend((0..adjustments_count).map(|_| ProjectionElem::Deref));
@@ -978,8 +949,8 @@ impl InferenceContext<'_> {
Pat::Missing | Pat::Wild => (),
Pat::Tuple { args, ellipsis } => {
let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
- let field_count = match self.result[tgt_pat].kind(Interner) {
- TyKind::Tuple(_, s) => s.len(Interner),
+ let field_count = match self.result[tgt_pat].kind() {
+ TyKind::Tuple(s) => s.len(),
_ => break 'reset_span_stack,
};
let fields = 0..field_count;
@@ -1125,9 +1096,9 @@ impl InferenceContext<'_> {
r
}
- fn analyze_closure(&mut self, closure: ClosureId) -> FnTrait {
- let InternedClosure(_, root) = self.db.lookup_intern_closure(closure.into());
- self.current_closure = Some(closure.into());
+ fn analyze_closure(&mut self, closure: InternedClosureId) -> FnTrait {
+ let InternedClosure(_, root) = self.db.lookup_intern_closure(closure);
+ self.current_closure = Some(closure);
let Expr::Closure { body, capture_by, .. } = &self.body[root] else {
unreachable!("Closure expression id is always closure");
};
@@ -1193,9 +1164,9 @@ impl InferenceContext<'_> {
self.result.expr_adjustments.remove(&callee).unwrap_or_default().into_vec();
self.write_fn_trait_method_resolution(
kind,
- &derefed_callee,
+ derefed_callee,
&mut adjustments,
- &callee_ty,
+ callee_ty,
&params,
expr,
);
@@ -1213,27 +1184,26 @@ impl InferenceContext<'_> {
///
/// These dependencies are collected in the main inference. We do a topological sort in this function. It
/// will consume the `deferred_closures` field and return its content in a sorted vector.
- fn sort_closures(&mut self) -> Vec<(ClosureId, Vec<(Ty, Ty, Vec<Ty>, ExprId)>)> {
+ fn sort_closures(
+ &mut self,
+ ) -> Vec<(InternedClosureId, Vec<(Ty<'db>, Ty<'db>, Vec<Ty<'db>>, ExprId)>)> {
let mut deferred_closures = mem::take(&mut self.deferred_closures);
- let mut dependents_count: FxHashMap<ClosureId, usize> =
- deferred_closures.keys().map(|it| ((*it).into(), 0)).collect();
+ let mut dependents_count: FxHashMap<InternedClosureId, usize> =
+ deferred_closures.keys().map(|it| (*it, 0)).collect();
for deps in self.closure_dependencies.values() {
for dep in deps {
- *dependents_count.entry((*dep).into()).or_default() += 1;
+ *dependents_count.entry(*dep).or_default() += 1;
}
}
- let mut queue: Vec<_> = deferred_closures
- .keys()
- .copied()
- .filter(|&it| dependents_count[&it.into()] == 0)
- .collect();
+ let mut queue: Vec<_> =
+ deferred_closures.keys().copied().filter(|&it| dependents_count[&it] == 0).collect();
let mut result = vec![];
while let Some(it) = queue.pop() {
if let Some(d) = deferred_closures.remove(&it) {
- result.push((it.into(), d));
+ result.push((it, d));
}
for &dep in self.closure_dependencies.get(&it).into_iter().flat_map(|it| it.iter()) {
- let cnt = dependents_count.get_mut(&dep.into()).unwrap();
+ let cnt = dependents_count.get_mut(&dep).unwrap();
*cnt -= 1;
if *cnt == 0 {
queue.push(dep);
@@ -1279,11 +1249,11 @@ impl InferenceContext<'_> {
}
/// Call this only when the last span in the stack isn't a split.
-fn apply_adjusts_to_place(
+fn apply_adjusts_to_place<'db>(
current_capture_span_stack: &mut Vec<MirSpan>,
- mut r: HirPlace,
- adjustments: &[Adjustment],
-) -> Option<HirPlace> {
+ mut r: HirPlace<'db>,
+ adjustments: &[Adjustment<'db>],
+) -> Option<HirPlace<'db>> {
let span = *current_capture_span_stack.last().expect("empty capture span stack");
for adj in adjustments {
match &adj.kind {
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index 62ce00a2e3..10c1f9c980 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -35,7 +35,6 @@
//! // and are then unable to coerce `&7i32` to `&mut i32`.
//! ```
-use chalk_ir::cast::Cast;
use hir_def::{
CallableDefId,
hir::{ExprId, ExprOrPatId},
@@ -45,22 +44,23 @@ use hir_def::{
use intern::sym;
use rustc_ast_ir::Mutability;
use rustc_type_ir::{
- TypeAndMut,
+ BoundVar, TypeAndMut,
error::TypeError,
- inherent::{IntoKind, Safety, Ty as _},
+ inherent::{Const as _, GenericArg as _, IntoKind, Region as _, Safety, SliceLike, Ty as _},
};
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};
use triomphe::Arc;
use crate::{
- Adjust, Adjustment, AutoBorrow, Interner, PointerCast, TargetFeatures, TraitEnvironment,
+ Adjust, Adjustment, AutoBorrow, PointerCast, TargetFeatures, TraitEnvironment,
autoderef::Autoderef,
db::{HirDatabase, InternedClosureId},
infer::{AllowTwoPhase, InferenceContext, TypeMismatch, unify::InferenceTable},
next_solver::{
- Binder, CallableIdWrapper, ClauseKind, CoercePredicate, DbInterner, ErrorGuaranteed,
- GenericArgs, PolyFnSig, PredicateKind, Region, SolverDefId, TraitRef, Ty, TyKind,
+ Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, CallableIdWrapper,
+ ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs,
+ PolyFnSig, PredicateKind, Region, RegionKind, SolverDefId, TraitRef, Ty, TyKind,
infer::{
DefineOpaqueTypes, InferCtxt, InferOk, InferResult,
relate::RelateResult,
@@ -93,7 +93,7 @@ struct Coerce<'a, 'b, 'db> {
cause: ObligationCause,
}
-type CoerceResult<'db> = InferResult<'db, (Vec<Adjustment>, Ty<'db>)>;
+type CoerceResult<'db> = InferResult<'db, (Vec<Adjustment<'db>>, Ty<'db>)>;
/// Coercing a mutable reference to an immutable works, while
/// coercing `&T` to `&mut T` should be forbidden.
@@ -103,7 +103,7 @@ fn coerce_mutbls<'db>(from_mutbl: Mutability, to_mutbl: Mutability) -> RelateRes
/// This always returns `Ok(...)`.
fn success<'db>(
- adj: Vec<Adjustment>,
+ adj: Vec<Adjustment<'db>>,
target: Ty<'db>,
obligations: PredicateObligations<'db>,
) -> CoerceResult<'db> {
@@ -118,7 +118,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
#[inline]
fn interner(&self) -> DbInterner<'db> {
- self.table.interner
+ self.table.interner()
}
#[inline]
@@ -182,17 +182,14 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
&mut self,
a: Ty<'db>,
b: Ty<'db>,
- adjustments: impl IntoIterator<Item = Adjustment>,
- final_adjustment: Adjust,
+ adjustments: impl IntoIterator<Item = Adjustment<'db>>,
+ final_adjustment: Adjust<'db>,
) -> CoerceResult<'db> {
self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| {
success(
adjustments
.into_iter()
- .chain(std::iter::once(Adjustment {
- target: ty.to_chalk(self.interner()),
- kind: final_adjustment,
- }))
+ .chain(std::iter::once(Adjustment { target: ty, kind: final_adjustment }))
.collect(),
ty,
obligations,
@@ -216,10 +213,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
if self.coerce_never {
return success(
- vec![Adjustment {
- kind: Adjust::NeverToAny,
- target: b.to_chalk(self.interner()),
- }],
+ vec![Adjustment { kind: Adjust::NeverToAny, target: b }],
b,
PredicateObligations::new(),
);
@@ -241,10 +235,9 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
&& let TyKind::Alias(rustc_type_ir::Opaque, opaque_ty) = b.kind()
&& let SolverDefId::InternedOpaqueTyId(opaque_ty_id) = opaque_ty.def_id
&& !matches!(a.kind(), TyKind::Infer(..) | TyKind::Alias(rustc_type_ir::Opaque, _))
- && let Some(ty) = tait_table.get(&opaque_ty_id.into())
+ && let Some(ty) = tait_table.get(&opaque_ty_id)
{
- b = ty.to_nextsolver(self.interner());
- b = self.table.shallow_resolve(b);
+ b = self.table.shallow_resolve(*ty);
}
let b = b;
@@ -474,7 +467,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
r_borrow_var.unwrap()
};
let derefd_ty_a = Ty::new_ref(
- autoderef.table.interner,
+ autoderef.table.interner(),
r,
referent_ty,
mutbl_b, // [1] above
@@ -547,11 +540,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
panic!("expected a ref type, got {:?}", ty);
};
adjustments.push(Adjustment {
- kind: Adjust::Borrow(AutoBorrow::Ref(
- region.to_chalk(self.interner()),
- mutbl_b.to_chalk(self.interner()),
- )),
- target: ty.to_chalk(self.interner()),
+ kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl_b)),
+ target: ty,
});
debug!("coerce_borrowed_pointer: succeeded ty={:?} adjustments={:?}", ty, adjustments);
@@ -655,20 +645,13 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
// implementation. If it happens that this coercion is a function argument,
// the reborrow in coerce_borrowed_ptr will pick it up.
// let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);
- let mutbl = mutbl_b.to_chalk(self.interner());
+ let mutbl = mutbl_b;
Some((
+ Adjustment { kind: Adjust::Deref(None), target: ty_a },
Adjustment {
- kind: Adjust::Deref(None),
- target: ty_a.to_chalk(self.interner()),
- },
- Adjustment {
- kind: Adjust::Borrow(AutoBorrow::Ref(
- r_borrow.to_chalk(self.interner()),
- mutbl,
- )),
- target: Ty::new_ref(self.interner(), r_borrow, ty_a, mutbl_b)
- .to_chalk(self.interner()),
+ kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)),
+ target: Ty::new_ref(self.interner(), r_borrow, ty_a, mutbl_b),
},
))
}
@@ -676,20 +659,16 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
coerce_mutbls(mt_a, mt_b)?;
Some((
+ Adjustment { kind: Adjust::Deref(None), target: ty_a },
Adjustment {
- kind: Adjust::Deref(None),
- target: ty_a.to_chalk(self.interner()),
- },
- Adjustment {
- kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b.to_chalk(self.interner()))),
- target: Ty::new_ptr(self.interner(), ty_a, mt_b).to_chalk(self.interner()),
+ kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)),
+ target: Ty::new_ptr(self.interner(), ty_a, mt_b),
},
))
}
_ => None,
};
- let coerce_source =
- reborrow.as_ref().map_or(source, |(_, r)| r.target.to_nextsolver(self.interner()));
+ let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target);
// Setup either a subtyping or a LUB relationship between
// the `CoerceUnsized` target type and the expected type.
@@ -834,7 +813,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
&mut self,
fn_ty_a: PolyFnSig<'db>,
b: Ty<'db>,
- adjustment: Option<Adjust>,
+ adjustment: Option<Adjust<'db>>,
) -> CoerceResult<'db> {
debug_assert!(self.table.shallow_resolve(b) == b);
@@ -849,7 +828,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
b,
adjustment.map(|kind| Adjustment {
kind,
- target: Ty::new_fn_ptr(this.interner(), fn_ty_a).to_chalk(this.interner()),
+ target: Ty::new_fn_ptr(this.interner(), fn_ty_a),
}),
Adjust::Pointer(PointerCast::UnsafeFnPointer),
)
@@ -961,9 +940,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
pointer_ty,
b,
[],
- Adjust::Pointer(PointerCast::ClosureFnPointer(
- safety.to_chalk(self.interner()),
- )),
+ Adjust::Pointer(PointerCast::ClosureFnPointer(safety)),
)
}
_ => self.unify(a, b),
@@ -991,11 +968,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
self.unify_and(
a_raw,
b,
- [Adjustment {
- kind: Adjust::Deref(None),
- target: mt_a.ty.to_chalk(self.interner()),
- }],
- Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b.to_chalk(self.interner()))),
+ [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }],
+ Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)),
)
} else if mt_a.mutbl != mutbl_b {
self.unify_and(a_raw, b, [], Adjust::Pointer(PointerCast::MutToConstPointer))
@@ -1011,7 +985,7 @@ pub(crate) enum CoerceNever {
Yes,
}
-impl<'db> InferenceContext<'db> {
+impl<'db> InferenceContext<'_, 'db> {
/// Attempt to coerce an expression to a type, and return the
/// adjusted type of the expression, if successful.
/// Adjustments are only recorded if the coercion succeeded.
@@ -1128,13 +1102,13 @@ impl<'db> InferenceContext<'db> {
// We have a LUB of prev_ty and new_ty, just return it.
Ok(ok) => return Ok(self.table.register_infer_ok(ok)),
Err(_) => (
- Some(prev_ty.fn_sig(self.table.interner)),
- Some(new_ty.fn_sig(self.table.interner)),
+ Some(prev_ty.fn_sig(self.table.interner())),
+ Some(new_ty.fn_sig(self.table.interner())),
),
}
}
(TyKind::Closure(_, args), TyKind::FnDef(..)) => {
- let b_sig = new_ty.fn_sig(self.table.interner);
+ let b_sig = new_ty.fn_sig(self.table.interner());
let a_sig = args.closure_sig_untupled().map_bound(|mut sig| {
sig.safety = b_sig.safety();
sig
@@ -1142,7 +1116,7 @@ impl<'db> InferenceContext<'db> {
(Some(a_sig), Some(b_sig))
}
(TyKind::FnDef(..), TyKind::Closure(_, args)) => {
- let a_sig = prev_ty.fn_sig(self.table.interner);
+ let a_sig = prev_ty.fn_sig(self.table.interner());
let b_sig = args.closure_sig_untupled().map_bound(|mut sig| {
sig.safety = a_sig.safety();
sig
@@ -1166,36 +1140,30 @@ impl<'db> InferenceContext<'db> {
.map(|ok| self.table.register_infer_ok(ok))?;
// Reify both sides and return the reified fn pointer type.
- let fn_ptr = Ty::new_fn_ptr(self.table.interner, sig);
+ let fn_ptr = Ty::new_fn_ptr(self.table.interner(), sig);
let prev_adjustment = match prev_ty.kind() {
- TyKind::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer(
- a_sig.safety().to_chalk(self.table.interner),
- )),
+ TyKind::Closure(..) => {
+ Adjust::Pointer(PointerCast::ClosureFnPointer(a_sig.safety()))
+ }
TyKind::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer),
_ => panic!("should not try to coerce a {prev_ty:?} to a fn pointer"),
};
let next_adjustment = match new_ty.kind() {
- TyKind::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer(
- b_sig.safety().to_chalk(self.table.interner),
- )),
+ TyKind::Closure(..) => {
+ Adjust::Pointer(PointerCast::ClosureFnPointer(b_sig.safety()))
+ }
TyKind::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer),
_ => panic!("should not try to coerce a {new_ty:?} to a fn pointer"),
};
for &expr in exprs {
self.write_expr_adj(
expr,
- Box::new([Adjustment {
- kind: prev_adjustment.clone(),
- target: fn_ptr.to_chalk(self.table.interner),
- }]),
+ Box::new([Adjustment { kind: prev_adjustment.clone(), target: fn_ptr }]),
);
}
self.write_expr_adj(
new,
- Box::new([Adjustment {
- kind: next_adjustment,
- target: fn_ptr.to_chalk(self.table.interner),
- }]),
+ Box::new([Adjustment { kind: next_adjustment, target: fn_ptr }]),
);
return Ok(fn_ptr);
}
@@ -1382,7 +1350,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
/// if necessary.
pub(crate) fn coerce(
&mut self,
- icx: &mut InferenceContext<'db>,
+ icx: &mut InferenceContext<'_, 'db>,
cause: &ObligationCause,
expression: ExprId,
expression_ty: Ty<'db>,
@@ -1404,19 +1372,12 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
/// removing a `;`).
pub(crate) fn coerce_forced_unit(
&mut self,
- icx: &mut InferenceContext<'db>,
+ icx: &mut InferenceContext<'_, 'db>,
expr: ExprId,
cause: &ObligationCause,
label_unit_as_expected: bool,
) {
- self.coerce_inner(
- icx,
- cause,
- expr,
- icx.result.standard_types.unit.to_nextsolver(icx.table.interner),
- true,
- label_unit_as_expected,
- )
+ self.coerce_inner(icx, cause, expr, icx.types.unit, true, label_unit_as_expected)
}
/// The inner coercion "engine". If `expression` is `None`, this
@@ -1424,7 +1385,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
/// `Nil`.
pub(crate) fn coerce_inner(
&mut self,
- icx: &mut InferenceContext<'db>,
+ icx: &mut InferenceContext<'_, 'db>,
cause: &ObligationCause,
expression: ExprId,
mut expression_ty: Ty<'db>,
@@ -1533,20 +1494,14 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
// emit or provide suggestions on how to fix the initial error.
icx.set_tainted_by_errors();
- self.final_ty = Some(Ty::new_error(icx.table.interner, ErrorGuaranteed));
+ self.final_ty = Some(icx.types.error);
icx.result.type_mismatches.insert(
expression.into(),
if label_expression_as_expected {
- TypeMismatch {
- expected: found.to_chalk(icx.table.interner),
- actual: expected.to_chalk(icx.table.interner),
- }
+ TypeMismatch { expected: found, actual: expected }
} else {
- TypeMismatch {
- expected: expected.to_chalk(icx.table.interner),
- actual: found.to_chalk(icx.table.interner),
- }
+ TypeMismatch { expected, actual: found }
},
);
}
@@ -1555,14 +1510,14 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
self.pushed += 1;
}
- pub(crate) fn complete(self, icx: &mut InferenceContext<'db>) -> Ty<'db> {
+ pub(crate) fn complete(self, icx: &mut InferenceContext<'_, 'db>) -> Ty<'db> {
if let Some(final_ty) = self.final_ty {
final_ty
} else {
// If we only had inputs that were of type `!` (or no
// inputs at all), then the final type is `!`.
assert_eq!(self.pushed, 0);
- icx.result.standard_types.never.to_nextsolver(icx.table.interner)
+ icx.types.never
}
}
}
@@ -1579,11 +1534,11 @@ fn coerce<'db>(
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
-) -> Result<(Vec<Adjustment>, crate::Ty), TypeError<DbInterner<'db>>> {
+) -> Result<(Vec<Adjustment<'db>>, crate::Ty), TypeError<DbInterner<'db>>> {
let mut table = InferenceTable::new(db, env);
- let vars = table.fresh_subst(tys.binders.as_slice(Interner));
- let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
- let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
+ let interner = table.interner();
+ let tys = tys.to_nextsolver(interner);
+ let ((ty1_with_vars, ty2_with_vars), vars) = table.infer_ctxt.instantiate_canonical(&tys);
let cause = ObligationCause::new();
// FIXME: Target features.
@@ -1597,36 +1552,67 @@ fn coerce<'db>(
use_lub: false,
target_features: &mut || (&target_features, TargetFeatureIsSafeInTarget::No),
};
- let InferOk { value: (adjustments, ty), obligations } = coerce.coerce(
- ty1_with_vars.to_nextsolver(coerce.table.interner),
- ty2_with_vars.to_nextsolver(coerce.table.interner),
- )?;
+ let InferOk { value: (adjustments, ty), obligations } =
+ coerce.coerce(ty1_with_vars, ty2_with_vars)?;
table.register_predicates(obligations);
// default any type vars that weren't unified back to their original bound vars
// (kind of hacky)
- let find_var = |iv| {
- vars.iter(Interner).position(|v| match v.interned() {
- chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
- chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
- chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
- } == Some(iv))
+ let mut fallback_ty = |debruijn, infer| {
+ let var = vars.var_values.iter().position(|arg| {
+ arg.as_type().is_some_and(|ty| match ty.kind() {
+ TyKind::Infer(it) => infer == it,
+ _ => false,
+ })
+ });
+ var.map_or_else(
+ || Ty::new_error(interner, ErrorGuaranteed),
+ |i| {
+ Ty::new_bound(
+ interner,
+ debruijn,
+ BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_usize(i) },
+ )
+ },
+ )
+ };
+ let mut fallback_const = |debruijn, infer| {
+ let var = vars.var_values.iter().position(|arg| {
+ arg.as_const().is_some_and(|ty| match ty.kind() {
+ ConstKind::Infer(it) => infer == it,
+ _ => false,
+ })
+ });
+ var.map_or_else(
+ || Const::new_error(interner, ErrorGuaranteed),
+ |i| Const::new_bound(interner, debruijn, BoundConst { var: BoundVar::from_usize(i) }),
+ )
};
- let fallback = |iv, kind, binder| match kind {
- chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv).map_or_else(
- || chalk_ir::TyKind::Error.intern(Interner).cast(Interner),
- |i| crate::BoundVar::new(binder, i).to_ty(Interner).cast(Interner),
- ),
- chalk_ir::VariableKind::Lifetime => find_var(iv).map_or_else(
- || crate::LifetimeData::Error.intern(Interner).cast(Interner),
- |i| crate::BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner),
- ),
- chalk_ir::VariableKind::Const(ty) => find_var(iv).map_or_else(
- || crate::unknown_const(ty.clone()).cast(Interner),
- |i| crate::BoundVar::new(binder, i).to_const(Interner, ty.clone()).cast(Interner),
- ),
+ let mut fallback_region = |debruijn, infer| {
+ let var = vars.var_values.iter().position(|arg| {
+ arg.as_region().is_some_and(|ty| match ty.kind() {
+ RegionKind::ReVar(it) => infer == it,
+ _ => false,
+ })
+ });
+ var.map_or_else(
+ || Region::error(interner),
+ |i| {
+ Region::new_bound(
+ interner,
+ debruijn,
+ BoundRegion { kind: BoundRegionKind::Anon, var: BoundVar::from_usize(i) },
+ )
+ },
+ )
};
// FIXME also map the types in the adjustments
// FIXME: We don't fallback correctly since this is done on `InferenceContext` and we only have `InferenceTable`.
- Ok((adjustments, table.resolve_with_fallback(ty.to_chalk(table.interner), &fallback)))
+ let ty = table.resolve_with_fallback(
+ ty,
+ &mut fallback_ty,
+ &mut fallback_const,
+ &mut fallback_region,
+ );
+ Ok((adjustments, ty.to_chalk(interner)))
}
diff --git a/crates/hir-ty/src/infer/diagnostics.rs b/crates/hir-ty/src/infer/diagnostics.rs
index 003364d433..39e70c262a 100644
--- a/crates/hir-ty/src/infer/diagnostics.rs
+++ b/crates/hir-ty/src/infer/diagnostics.rs
@@ -12,11 +12,11 @@ use hir_def::expr_store::path::Path;
use hir_def::{hir::ExprOrPatId, resolver::Resolver};
use la_arena::{Idx, RawIdx};
-use crate::lower::LifetimeElisionKind;
use crate::{
- InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringContext, TyLoweringDiagnostic,
+ InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic,
db::HirDatabase,
- lower::path::{PathDiagnosticCallback, PathLoweringContext},
+ lower_nextsolver::path::{PathDiagnosticCallback, PathLoweringContext},
+ lower_nextsolver::{LifetimeElisionKind, TyLoweringContext},
};
// Unfortunately, this struct needs to use interior mutability (but we encapsulate it)
@@ -24,10 +24,10 @@ use crate::{
// to our resolver and so we cannot have mutable reference, but we really want to have
// ability to dispatch diagnostics during this work otherwise the code becomes a complete mess.
#[derive(Debug, Default, Clone)]
-pub(super) struct Diagnostics(RefCell<Vec<InferenceDiagnostic>>);
+pub(super) struct Diagnostics<'db>(RefCell<Vec<InferenceDiagnostic<'db>>>);
-impl Diagnostics {
- pub(super) fn push(&self, diagnostic: InferenceDiagnostic) {
+impl<'db> Diagnostics<'db> {
+ pub(super) fn push(&self, diagnostic: InferenceDiagnostic<'db>) {
self.0.borrow_mut().push(diagnostic);
}
@@ -41,32 +41,32 @@ impl Diagnostics {
);
}
- pub(super) fn finish(self) -> Vec<InferenceDiagnostic> {
+ pub(super) fn finish(self) -> Vec<InferenceDiagnostic<'db>> {
self.0.into_inner()
}
}
-pub(crate) struct PathDiagnosticCallbackData<'a> {
+pub(crate) struct PathDiagnosticCallbackData<'a, 'db> {
node: ExprOrPatId,
- diagnostics: &'a Diagnostics,
+ diagnostics: &'a Diagnostics<'db>,
}
-pub(super) struct InferenceTyLoweringContext<'a> {
- ctx: TyLoweringContext<'a>,
- diagnostics: &'a Diagnostics,
+pub(super) struct InferenceTyLoweringContext<'db, 'a> {
+ ctx: TyLoweringContext<'db, 'a>,
+ diagnostics: &'a Diagnostics<'db>,
source: InferenceTyDiagnosticSource,
}
-impl<'a> InferenceTyLoweringContext<'a> {
+impl<'db, 'a> InferenceTyLoweringContext<'db, 'a> {
#[inline]
pub(super) fn new(
- db: &'a dyn HirDatabase,
- resolver: &'a Resolver<'_>,
+ db: &'db dyn HirDatabase,
+ resolver: &'a Resolver<'db>,
store: &'a ExpressionStore,
- diagnostics: &'a Diagnostics,
+ diagnostics: &'a Diagnostics<'db>,
source: InferenceTyDiagnosticSource,
generic_def: GenericDefId,
- lifetime_elision: LifetimeElisionKind,
+ lifetime_elision: LifetimeElisionKind<'db>,
) -> Self {
Self {
ctx: TyLoweringContext::new(db, resolver, store, generic_def, lifetime_elision),
@@ -80,7 +80,7 @@ impl<'a> InferenceTyLoweringContext<'a> {
&'b mut self,
path: &'b Path,
node: ExprOrPatId,
- ) -> PathLoweringContext<'b, 'a> {
+ ) -> PathLoweringContext<'b, 'a, 'db> {
let on_diagnostic = PathDiagnosticCallback {
data: Either::Right(PathDiagnosticCallbackData { diagnostics: self.diagnostics, node }),
callback: |data, _, diag| {
@@ -96,7 +96,7 @@ impl<'a> InferenceTyLoweringContext<'a> {
pub(super) fn at_path_forget_diagnostics<'b>(
&'b mut self,
path: &'b Path,
- ) -> PathLoweringContext<'b, 'a> {
+ ) -> PathLoweringContext<'b, 'a, 'db> {
let on_diagnostic = PathDiagnosticCallback {
data: Either::Right(PathDiagnosticCallbackData {
diagnostics: self.diagnostics,
@@ -113,8 +113,8 @@ impl<'a> InferenceTyLoweringContext<'a> {
}
}
-impl<'a> Deref for InferenceTyLoweringContext<'a> {
- type Target = TyLoweringContext<'a>;
+impl<'db, 'a> Deref for InferenceTyLoweringContext<'db, 'a> {
+ type Target = TyLoweringContext<'db, 'a>;
#[inline]
fn deref(&self) -> &Self::Target {
@@ -122,14 +122,14 @@ impl<'a> Deref for InferenceTyLoweringContext<'a> {
}
}
-impl DerefMut for InferenceTyLoweringContext<'_> {
+impl DerefMut for InferenceTyLoweringContext<'_, '_> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.ctx
}
}
-impl Drop for InferenceTyLoweringContext<'_> {
+impl Drop for InferenceTyLoweringContext<'_, '_> {
#[inline]
fn drop(&mut self) {
self.diagnostics
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index ddf632c1c8..b4140d88db 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -2,12 +2,11 @@
use std::{iter::repeat_with, mem};
-use chalk_ir::{DebruijnIndex, Mutability, TyVariableKind, cast::Cast};
use either::Either;
use hir_def::hir::ClosureKind;
use hir_def::{
BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
- expr_store::path::{GenericArg, GenericArgs, Path},
+ expr_store::path::{GenericArg as HirGenericArg, GenericArgs as HirGenericArgs, Path},
hir::{
ArithOp, Array, AsmOperand, AsmOptions, BinaryOp, Expr, ExprId, ExprOrPatId, LabelId,
Literal, Pat, PatId, Statement, UnaryOp, generics::GenericParamDataRef,
@@ -17,19 +16,19 @@ use hir_def::{
};
use hir_expand::name::Name;
use intern::sym;
-use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike, Ty as _};
-use stdx::always;
+use rustc_ast_ir::Mutability;
+use rustc_type_ir::{
+ AliasTyKind, InferTy, Interner,
+ inherent::{AdtDef, GenericArgs as _, IntoKind, SliceLike, Ty as _},
+};
use syntax::ast::RangeOp;
use tracing::debug;
-use crate::autoderef::overloaded_deref_ty;
-use crate::next_solver::infer::DefineOpaqueTypes;
-use crate::next_solver::obligation_ctxt::ObligationCtxt;
-use crate::next_solver::{DbInterner, ErrorGuaranteed};
use crate::{
- Adjust, Adjustment, AdtId, AutoBorrow, CallableDefId, CallableSig, DeclContext, DeclOrigin,
- IncorrectGenericsLenKind, Interner, LifetimeElisionKind, Rawness, Scalar, Substitution,
- TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, consteval,
+ Adjust, Adjustment, AutoBorrow, CallableDefId, DeclContext, DeclOrigin,
+ IncorrectGenericsLenKind, Rawness, TraitEnvironment,
+ autoderef::overloaded_deref_ty,
+ consteval_nextsolver,
generics::generics,
infer::{
AllowTwoPhase, BreakableKind,
@@ -38,18 +37,20 @@ use crate::{
pat::contains_explicit_ref_binding,
},
lang_items::lang_items_for_bin_op,
- lower::{
- ParamLoweringMode, lower_to_chalk_mutability,
+ lower_nextsolver::{
+ LifetimeElisionKind, lower_mutability,
path::{GenericArgsLowerer, TypeLikeConst, substs_from_args_and_bindings},
},
- mapping::{ToChalk, from_chalk},
method_resolution::{self, VisibleFromModule},
next_solver::{
- infer::traits::ObligationCause,
- mapping::{ChalkToNextSolver, NextSolverToChalk},
+ AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, TraitRef, Ty, TyKind,
+ TypeError,
+ infer::{
+ DefineOpaqueTypes, InferOk,
+ traits::{Obligation, ObligationCause},
+ },
+ obligation_ctxt::ObligationCtxt,
},
- primitive::{self, UintTy},
- static_lifetime, to_chalk_trait_id,
traits::FnTrait,
};
@@ -64,27 +65,30 @@ pub(crate) enum ExprIsRead {
No,
}
-impl<'db> InferenceContext<'db> {
+impl<'db> InferenceContext<'_, 'db> {
pub(crate) fn infer_expr(
&mut self,
tgt_expr: ExprId,
- expected: &Expectation,
+ expected: &Expectation<'db>,
is_read: ExprIsRead,
- ) -> Ty {
+ ) -> Ty<'db> {
let ty = self.infer_expr_inner(tgt_expr, expected, is_read);
if let Some(expected_ty) = expected.only_has_type(&mut self.table) {
- let could_unify = self.unify(&ty, &expected_ty);
+ let could_unify = self.unify(ty, expected_ty);
if !could_unify {
- self.result.type_mismatches.insert(
- tgt_expr.into(),
- TypeMismatch { expected: expected_ty, actual: ty.clone() },
- );
+ self.result
+ .type_mismatches
+ .insert(tgt_expr.into(), TypeMismatch { expected: expected_ty, actual: ty });
}
}
ty
}
- pub(crate) fn infer_expr_no_expect(&mut self, tgt_expr: ExprId, is_read: ExprIsRead) -> Ty {
+ pub(crate) fn infer_expr_no_expect(
+ &mut self,
+ tgt_expr: ExprId,
+ is_read: ExprIsRead,
+ ) -> Ty<'db> {
self.infer_expr_inner(tgt_expr, &Expectation::None, is_read)
}
@@ -93,9 +97,9 @@ impl<'db> InferenceContext<'db> {
pub(super) fn infer_expr_coerce(
&mut self,
expr: ExprId,
- expected: &Expectation,
+ expected: &Expectation<'db>,
is_read: ExprIsRead,
- ) -> Ty {
+ ) -> Ty<'db> {
let ty = self.infer_expr_inner(expr, expected, is_read);
if let Some(target) = expected.only_has_type(&mut self.table) {
let coerce_never = if self.expr_guaranteed_to_constitute_read_for_never(expr, is_read) {
@@ -103,19 +107,12 @@ impl<'db> InferenceContext<'db> {
} else {
CoerceNever::No
};
- match self.coerce(
- expr.into(),
- ty.to_nextsolver(self.table.interner),
- target.to_nextsolver(self.table.interner),
- AllowTwoPhase::No,
- coerce_never,
- ) {
- Ok(res) => res.to_chalk(self.table.interner),
+ match self.coerce(expr.into(), ty, target, AllowTwoPhase::No, coerce_never) {
+ Ok(res) => res,
Err(_) => {
- self.result.type_mismatches.insert(
- expr.into(),
- TypeMismatch { expected: target.clone(), actual: ty.clone() },
- );
+ self.result
+ .type_mismatches
+ .insert(expr.into(), TypeMismatch { expected: target, actual: ty });
target
}
}
@@ -255,42 +252,34 @@ impl<'db> InferenceContext<'db> {
fn infer_expr_coerce_never(
&mut self,
expr: ExprId,
- expected: &Expectation,
+ expected: &Expectation<'db>,
is_read: ExprIsRead,
- ) -> Ty {
+ ) -> Ty<'db> {
let ty = self.infer_expr_inner(expr, expected, is_read);
// While we don't allow *arbitrary* coercions here, we *do* allow
// coercions from `!` to `expected`.
if ty.is_never() {
if let Some(adjustments) = self.result.expr_adjustments.get(&expr) {
return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &**adjustments {
- target.clone()
+ *target
} else {
self.err_ty()
};
}
if let Some(target) = expected.only_has_type(&mut self.table) {
- self.coerce(
- expr.into(),
- ty.to_nextsolver(self.table.interner),
- target.to_nextsolver(self.table.interner),
- AllowTwoPhase::No,
- CoerceNever::Yes,
- )
- .expect("never-to-any coercion should always succeed")
- .to_chalk(self.table.interner)
+ self.coerce(expr.into(), ty, target, AllowTwoPhase::No, CoerceNever::Yes)
+ .expect("never-to-any coercion should always succeed")
} else {
ty
}
} else {
if let Some(expected_ty) = expected.only_has_type(&mut self.table) {
- let could_unify = self.unify(&ty, &expected_ty);
+ let could_unify = self.unify(ty, expected_ty);
if !could_unify {
- self.result.type_mismatches.insert(
- expr.into(),
- TypeMismatch { expected: expected_ty, actual: ty.clone() },
- );
+ self.result
+ .type_mismatches
+ .insert(expr.into(), TypeMismatch { expected: expected_ty, actual: ty });
}
}
ty
@@ -301,9 +290,9 @@ impl<'db> InferenceContext<'db> {
fn infer_expr_inner(
&mut self,
tgt_expr: ExprId,
- expected: &Expectation,
+ expected: &Expectation<'db>,
is_read: ExprIsRead,
- ) -> Ty {
+ ) -> Ty<'db> {
self.db.unwind_if_revision_cancelled();
let expr = &self.body[tgt_expr];
@@ -314,7 +303,7 @@ impl<'db> InferenceContext<'db> {
let expected = &expected.adjust_for_branches(&mut self.table);
self.infer_expr_coerce_never(
condition,
- &Expectation::HasType(self.result.standard_types.bool_.clone()),
+ &Expectation::HasType(self.types.bool),
ExprIsRead::Yes,
);
@@ -327,27 +316,15 @@ impl<'db> InferenceContext<'db> {
coercion_sites[1] = else_branch;
}
let mut coerce = CoerceMany::with_coercion_sites(
- expected
- .coercion_target_type(&mut self.table)
- .to_nextsolver(self.table.interner),
+ expected.coercion_target_type(&mut self.table),
&coercion_sites,
);
- coerce.coerce(
- self,
- &ObligationCause::new(),
- then_branch,
- then_ty.to_nextsolver(self.table.interner),
- );
+ coerce.coerce(self, &ObligationCause::new(), then_branch, then_ty);
match else_branch {
Some(else_branch) => {
let else_ty = self.infer_expr_inner(else_branch, expected, ExprIsRead::Yes);
let else_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
- coerce.coerce(
- self,
- &ObligationCause::new(),
- else_branch,
- else_ty.to_nextsolver(self.table.interner),
- );
+ coerce.coerce(self, &ObligationCause::new(), else_branch, else_ty);
self.diverges = condition_diverges | then_diverges & else_diverges;
}
None => {
@@ -356,7 +333,7 @@ impl<'db> InferenceContext<'db> {
}
}
- coerce.complete(self).to_chalk(self.table.interner)
+ coerce.complete(self)
}
&Expr::Let { pat, expr } => {
let child_is_read = if self.pat_guaranteed_to_constitute_read_for_never(pat) {
@@ -367,10 +344,10 @@ impl<'db> InferenceContext<'db> {
let input_ty = self.infer_expr(expr, &Expectation::none(), child_is_read);
self.infer_top_pat(
pat,
- &input_ty,
+ input_ty,
Some(DeclContext { origin: DeclOrigin::LetExpr }),
);
- self.result.standard_types.bool_.clone()
+ self.types.bool
}
Expr::Block { statements, tail, label, id } => {
self.infer_block(tgt_expr, *id, statements, *tail, *label, expected)
@@ -390,12 +367,12 @@ impl<'db> InferenceContext<'db> {
&Expr::Loop { body, label } => {
// FIXME: should be:
// let ty = expected.coercion_target_type(&mut self.table);
- let ty = self.table.new_type_var();
+ let ty = self.table.next_ty_var();
let (breaks, ()) =
self.with_breakable_ctx(BreakableKind::Loop, Some(ty), label, |this| {
this.infer_expr(
body,
- &Expectation::HasType(TyBuilder::unit()),
+ &Expectation::HasType(this.types.unit),
ExprIsRead::Yes,
);
});
@@ -405,7 +382,7 @@ impl<'db> InferenceContext<'db> {
self.diverges = Diverges::Maybe;
breaks
}
- None => self.result.standard_types.never.clone(),
+ None => self.types.never,
}
}
Expr::Closure { body, args, ret_type, arg_types, closure_kind, capture_by: _ } => self
@@ -438,32 +415,30 @@ impl<'db> InferenceContext<'db> {
if arms.is_empty() {
self.diverges = Diverges::Always;
- self.result.standard_types.never.clone()
+ self.types.never
} else {
let matchee_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let mut all_arms_diverge = Diverges::Always;
for arm in arms.iter() {
- let input_ty = self.table.structurally_resolve_type(&input_ty);
- self.infer_top_pat(arm.pat, &input_ty, None);
+ let input_ty = self.table.structurally_resolve_type(input_ty);
+ self.infer_top_pat(arm.pat, input_ty, None);
}
let expected = expected.adjust_for_branches(&mut self.table);
let result_ty = match &expected {
// We don't coerce to `()` so that if the match expression is a
// statement it's branches can have any consistent type.
- Expectation::HasType(ty) if *ty != self.result.standard_types.unit => {
- ty.clone()
- }
- _ => self.table.new_type_var(),
+ Expectation::HasType(ty) if *ty != self.types.unit => *ty,
+ _ => self.table.next_ty_var(),
};
- let mut coerce = CoerceMany::new(result_ty.to_nextsolver(self.table.interner));
+ let mut coerce = CoerceMany::new(result_ty);
for arm in arms.iter() {
if let Some(guard_expr) = arm.guard {
self.diverges = Diverges::Maybe;
self.infer_expr_coerce_never(
guard_expr,
- &Expectation::HasType(self.result.standard_types.bool_.clone()),
+ &Expectation::HasType(self.types.bool),
ExprIsRead::Yes,
);
}
@@ -471,17 +446,12 @@ impl<'db> InferenceContext<'db> {
let arm_ty = self.infer_expr_inner(arm.expr, &expected, ExprIsRead::Yes);
all_arms_diverge &= self.diverges;
- coerce.coerce(
- self,
- &ObligationCause::new(),
- arm.expr,
- arm_ty.to_nextsolver(self.table.interner),
- );
+ coerce.coerce(self, &ObligationCause::new(), arm.expr, arm_ty);
}
self.diverges = matchee_diverges | all_arms_diverge;
- coerce.complete(self).to_chalk(self.table.interner)
+ coerce.complete(self)
}
}
Expr::Path(p) => self.infer_expr_path(p, tgt_expr.into(), tgt_expr),
@@ -493,13 +463,13 @@ impl<'db> InferenceContext<'db> {
bad_value_break: false,
});
};
- self.result.standard_types.never.clone()
+ self.types.never
}
&Expr::Break { expr, label } => {
let val_ty = if let Some(expr) = expr {
let opt_coerce_to = match find_breakable(&mut self.breakables, label) {
Some(ctxt) => match &ctxt.coerce {
- Some(coerce) => coerce.expected_ty().to_chalk(self.table.interner),
+ Some(coerce) => coerce.expected_ty(),
None => {
self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
expr: tgt_expr,
@@ -517,7 +487,7 @@ impl<'db> InferenceContext<'db> {
ExprIsRead::Yes,
)
} else {
- TyBuilder::unit()
+ self.types.unit
};
match find_breakable(&mut self.breakables, label) {
@@ -527,7 +497,7 @@ impl<'db> InferenceContext<'db> {
self,
&ObligationCause::new(),
expr.unwrap_or(tgt_expr),
- val_ty.to_nextsolver(self.table.interner),
+ val_ty,
);
// Avoiding borrowck
@@ -546,12 +516,12 @@ impl<'db> InferenceContext<'db> {
});
}
}
- self.result.standard_types.never.clone()
+ self.types.never
}
&Expr::Return { expr } => self.infer_expr_return(tgt_expr, expr),
&Expr::Become { expr } => self.infer_expr_become(expr),
Expr::Yield { expr } => {
- if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
+ if let Some((resume_ty, yield_ty)) = self.resume_yield_tys {
if let Some(expr) = expr {
self.infer_expr_coerce(
*expr,
@@ -559,11 +529,11 @@ impl<'db> InferenceContext<'db> {
ExprIsRead::Yes,
);
} else {
- let unit = self.result.standard_types.unit.clone();
+ let unit = self.types.unit;
let _ = self.coerce(
tgt_expr.into(),
- unit.to_nextsolver(self.table.interner),
- yield_ty.to_nextsolver(self.table.interner),
+ unit,
+ yield_ty,
AllowTwoPhase::No,
CoerceNever::Yes,
);
@@ -571,33 +541,30 @@ impl<'db> InferenceContext<'db> {
resume_ty
} else {
// FIXME: report error (yield expr in non-coroutine)
- self.result.standard_types.unknown.clone()
+ self.types.error
}
}
Expr::Yeet { expr } => {
if let &Some(expr) = expr {
self.infer_expr_no_expect(expr, ExprIsRead::Yes);
}
- self.result.standard_types.never.clone()
+ self.types.never
}
Expr::RecordLit { path, fields, spread, .. } => {
let (ty, def_id) = self.resolve_variant(tgt_expr.into(), path.as_deref(), false);
if let Some(t) = expected.only_has_type(&mut self.table) {
- self.unify(&ty, &t);
+ self.unify(ty, t);
}
- let substs = ty
- .as_adt()
- .map(|(_, s)| s.clone())
- .unwrap_or_else(|| Substitution::empty(Interner));
+ let substs = ty.as_adt().map(|(_, s)| s).unwrap_or(self.types.empty_args);
if let Some(variant) = def_id {
self.write_variant_resolution(tgt_expr.into(), variant);
}
match def_id {
_ if fields.is_empty() => {}
Some(def) => {
- let field_types = self.db.field_types(def);
+ let field_types = self.db.field_types_ns(def);
let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
for field in fields.iter() {
@@ -628,7 +595,7 @@ impl<'db> InferenceContext<'db> {
}
};
let field_ty = field_def.map_or(self.err_ty(), |it| {
- field_types[it].clone().substitute(Interner, &substs)
+ field_types[it].instantiate(self.interner(), &substs)
});
// Field type might have some unknown types
@@ -649,7 +616,7 @@ impl<'db> InferenceContext<'db> {
}
}
if let Some(expr) = spread {
- self.infer_expr(*expr, &Expectation::has_type(ty.clone()), ExprIsRead::Yes);
+ self.infer_expr(*expr, &Expectation::has_type(ty), ExprIsRead::Yes);
}
ty
}
@@ -660,21 +627,13 @@ impl<'db> InferenceContext<'db> {
}
Expr::Cast { expr, type_ref } => {
let cast_ty = self.make_body_ty(*type_ref);
- let expr_ty = self.infer_expr(
- *expr,
- &Expectation::Castable(cast_ty.clone()),
- ExprIsRead::Yes,
- );
- self.deferred_cast_checks.push(CastCheck::new(
- tgt_expr,
- *expr,
- expr_ty,
- cast_ty.clone(),
- ));
+ let expr_ty =
+ self.infer_expr(*expr, &Expectation::Castable(cast_ty), ExprIsRead::Yes);
+ self.deferred_cast_checks.push(CastCheck::new(tgt_expr, *expr, expr_ty, cast_ty));
cast_ty
}
Expr::Ref { expr, rawness, mutability } => {
- let mutability = lower_to_chalk_mutability(*mutability);
+ let mutability = lower_mutability(*mutability);
let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = expected
.only_has_type(&mut self.table)
.as_ref()
@@ -688,24 +647,23 @@ impl<'db> InferenceContext<'db> {
// FIXME: record type error - expected reference but found ptr,
// which cannot be coerced
}
- Expectation::rvalue_hint(self, Ty::clone(exp_inner))
+ Expectation::rvalue_hint(self, exp_inner)
} else {
Expectation::none()
};
let inner_ty = self.infer_expr_inner(*expr, &expectation, ExprIsRead::Yes);
match rawness {
- Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
+ Rawness::RawPtr => Ty::new_ptr(self.interner(), inner_ty, mutability),
Rawness::Ref => {
- let lt = self.table.new_lifetime_var();
- TyKind::Ref(mutability, lt, inner_ty)
+ let lt = self.table.next_region_var();
+ Ty::new_ref(self.interner(), lt, inner_ty, mutability)
}
}
- .intern(Interner)
}
&Expr::Box { expr } => self.infer_expr_box(expr, expected),
Expr::UnaryOp { expr, op } => {
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none(), ExprIsRead::Yes);
- let inner_ty = self.table.structurally_resolve_type(&inner_ty);
+ let inner_ty = self.table.try_structurally_resolve_type(inner_ty);
// FIXME: Note down method resolution her
match op {
UnaryOp::Deref => {
@@ -716,49 +674,38 @@ impl<'db> InferenceContext<'db> {
{
// FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
// the mutability is not wrong, and will be fixed in `self.infer_mut`).
- self.write_method_resolution(
- tgt_expr,
- deref_fn,
- Substitution::empty(Interner),
- );
+ self.write_method_resolution(tgt_expr, deref_fn, self.types.empty_args);
}
- if let Some(derefed) =
- inner_ty.to_nextsolver(self.table.interner).builtin_deref(self.db, true)
- {
- self.table
- .structurally_resolve_type(&derefed.to_chalk(self.table.interner))
+ if let Some(derefed) = inner_ty.builtin_deref(self.db, true) {
+ self.table.try_structurally_resolve_type(derefed)
} else {
- let infer_ok = overloaded_deref_ty(
- &self.table,
- inner_ty.to_nextsolver(self.table.interner),
- );
+ let infer_ok = overloaded_deref_ty(&self.table, inner_ty);
match infer_ok {
- Some(infer_ok) => self
- .table
- .register_infer_ok(infer_ok)
- .to_chalk(self.table.interner),
+ Some(infer_ok) => self.table.register_infer_ok(infer_ok),
None => self.err_ty(),
}
}
}
UnaryOp::Neg => {
- match inner_ty.kind(Interner) {
+ match inner_ty.kind() {
// Fast path for builtins
- TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_))
- | TyKind::InferenceVar(
- _,
- TyVariableKind::Integer | TyVariableKind::Float,
- ) => inner_ty,
+ TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
+ | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => inner_ty,
// Otherwise we resolve via the std::ops::Neg trait
_ => self
.resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
}
}
UnaryOp::Not => {
- match inner_ty.kind(Interner) {
+ match inner_ty.kind() {
// Fast path for builtins
- TyKind::Scalar(Scalar::Bool | Scalar::Int(_) | Scalar::Uint(_))
- | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty,
+ TyKind::Bool
+ | TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
+ | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => inner_ty,
// Otherwise we resolve via the std::ops::Not trait
_ => self
.resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
@@ -768,18 +715,10 @@ impl<'db> InferenceContext<'db> {
}
Expr::BinaryOp { lhs, rhs, op } => match op {
Some(BinaryOp::LogicOp(_)) => {
- let bool_ty = self.result.standard_types.bool_.clone();
- self.infer_expr_coerce(
- *lhs,
- &Expectation::HasType(bool_ty.clone()),
- ExprIsRead::Yes,
- );
+ let bool_ty = self.types.bool;
+ self.infer_expr_coerce(*lhs, &Expectation::HasType(bool_ty), ExprIsRead::Yes);
let lhs_diverges = self.diverges;
- self.infer_expr_coerce(
- *rhs,
- &Expectation::HasType(bool_ty.clone()),
- ExprIsRead::Yes,
- );
+ self.infer_expr_coerce(*rhs, &Expectation::HasType(bool_ty), ExprIsRead::Yes);
// Depending on the LHS' value, the RHS can never execute.
self.diverges = lhs_diverges;
bool_ty
@@ -826,14 +765,14 @@ impl<'db> InferenceContext<'db> {
let is_destructuring_assignment = lhs_ty.is_none();
if let Some(lhs_ty) = lhs_ty {
- self.write_pat_ty(target, lhs_ty.clone());
+ self.write_pat_ty(target, lhs_ty);
self.infer_expr_coerce(value, &Expectation::has_type(lhs_ty), ExprIsRead::No);
} else {
let rhs_ty = self.infer_expr(value, &Expectation::none(), ExprIsRead::Yes);
let resolver_guard =
self.resolver.update_to_inner_scope(self.db, self.owner, tgt_expr);
self.inside_assignment = true;
- self.infer_top_pat(target, &rhs_ty, None);
+ self.infer_top_pat(target, rhs_ty, None);
self.inside_assignment = false;
self.resolver.reset_to_guard(resolver_guard);
}
@@ -844,43 +783,49 @@ impl<'db> InferenceContext<'db> {
// assignments into blocks.
self.table.new_maybe_never_var()
} else {
- self.result.standard_types.unit.clone()
+ self.types.unit
}
}
Expr::Range { lhs, rhs, range_type } => {
let lhs_ty =
lhs.map(|e| self.infer_expr_inner(e, &Expectation::none(), ExprIsRead::Yes));
- let rhs_expect = lhs_ty
- .as_ref()
- .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone()));
+ let rhs_expect =
+ lhs_ty.as_ref().map_or_else(Expectation::none, |ty| Expectation::has_type(*ty));
let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect, ExprIsRead::Yes));
+ let single_arg_adt = |adt, ty: Ty<'db>| {
+ Ty::new_adt(
+ self.interner(),
+ adt,
+ GenericArgs::new_from_iter(self.interner(), [ty.into()]),
+ )
+ };
match (range_type, lhs_ty, rhs_ty) {
(RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
- Some(adt) => TyBuilder::adt(self.db, adt).build(),
+ Some(adt) => Ty::new_adt(self.interner(), adt, self.types.empty_args),
None => self.err_ty(),
},
(RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
- Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
+ Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
},
(RangeOp::Inclusive, None, Some(ty)) => {
match self.resolve_range_to_inclusive() {
- Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
+ Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
}
}
(RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
- Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
+ Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
},
(RangeOp::Inclusive, Some(_), Some(ty)) => {
match self.resolve_range_inclusive() {
- Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
+ Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
}
}
(RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
- Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
+ Some(adt) => single_arg_adt(adt, ty),
None => self.err_ty(),
},
(RangeOp::Inclusive, _, None) => self.err_ty(),
@@ -891,8 +836,7 @@ impl<'db> InferenceContext<'db> {
let index_ty = self.infer_expr(*index, &Expectation::none(), ExprIsRead::Yes);
if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) {
- let canonicalized =
- self.canonicalize(base_ty.clone().to_nextsolver(self.table.interner));
+ let canonicalized = self.canonicalize(base_ty);
let receiver_adjustments = method_resolution::resolve_indexing_op(
&mut self.table,
canonicalized,
@@ -905,142 +849,133 @@ impl<'db> InferenceContext<'db> {
// mutability will be fixed up in `InferenceContext::infer_mut`;
adj.push(Adjustment::borrow(
+ self.interner(),
Mutability::Not,
- self_ty.clone(),
- self.table.new_lifetime_var(),
+ self_ty,
+ self.table.next_region_var(),
));
self.write_expr_adj(*base, adj.into_boxed_slice());
if let Some(func) = index_trait
.trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::index))
{
- let subst = TyBuilder::subst_for_def(self.db, index_trait, None);
- if subst.remaining() != 2 {
- return self.err_ty();
- }
- let subst = subst.push(self_ty.clone()).push(index_ty.clone()).build();
+ let subst = GenericArgs::new_from_iter(
+ self.interner(),
+ [self_ty.into(), index_ty.into()],
+ );
self.write_method_resolution(tgt_expr, func, subst);
}
let assoc = self.resolve_ops_index_output();
- self.resolve_associated_type_with_params(
- self_ty,
- assoc,
- &[index_ty.cast(Interner)],
- )
+ self.resolve_associated_type_with_params(self_ty, assoc, &[index_ty.into()])
} else {
self.err_ty()
}
}
Expr::Tuple { exprs, .. } => {
- let mut tys = match expected
- .only_has_type(&mut self.table)
- .as_ref()
- .map(|t| t.kind(Interner))
- {
- Some(TyKind::Tuple(_, substs)) => substs
- .iter(Interner)
- .map(|a| a.assert_ty_ref(Interner).clone())
- .chain(repeat_with(|| self.table.new_type_var()))
- .take(exprs.len())
- .collect::<Vec<_>>(),
- _ => (0..exprs.len()).map(|_| self.table.new_type_var()).collect(),
- };
+ let mut tys =
+ match expected.only_has_type(&mut self.table).as_ref().map(|t| t.kind()) {
+ Some(TyKind::Tuple(substs)) => substs
+ .iter()
+ .chain(repeat_with(|| self.table.next_ty_var()))
+ .take(exprs.len())
+ .collect::<Vec<_>>(),
+ _ => (0..exprs.len()).map(|_| self.table.next_ty_var()).collect(),
+ };
for (expr, ty) in exprs.iter().zip(tys.iter_mut()) {
- *ty = self.infer_expr_coerce(
- *expr,
- &Expectation::has_type(ty.clone()),
- ExprIsRead::Yes,
- );
+ *ty =
+ self.infer_expr_coerce(*expr, &Expectation::has_type(*ty), ExprIsRead::Yes);
}
- TyKind::Tuple(tys.len(), Substitution::from_iter(Interner, tys)).intern(Interner)
+ Ty::new_tup(self.interner(), &tys)
}
Expr::Array(array) => self.infer_expr_array(array, expected),
Expr::Literal(lit) => match lit {
- Literal::Bool(..) => self.result.standard_types.bool_.clone(),
- Literal::String(..) => {
- TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner))
- .intern(Interner)
- }
+ Literal::Bool(..) => self.types.bool,
+ Literal::String(..) => self.types.static_str_ref,
Literal::ByteString(bs) => {
- let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
+ let byte_type = self.types.u8;
- let len = consteval::usize_const(
+ let len = consteval_nextsolver::usize_const(
self.db,
Some(bs.len() as u128),
self.resolver.krate(),
);
- let array_type = TyKind::Array(byte_type, len).intern(Interner);
- TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(Interner)
+ let array_type = Ty::new_array_with_const_len(self.interner(), byte_type, len);
+ Ty::new_ref(self.interner(), self.types.re_static, array_type, Mutability::Not)
}
- Literal::CString(..) => TyKind::Ref(
- Mutability::Not,
- static_lifetime(),
+ Literal::CString(..) => Ty::new_ref(
+ self.interner(),
+ self.types.re_static,
self.resolve_lang_item(LangItem::CStr)
.and_then(LangItemTarget::as_struct)
.map_or_else(
|| self.err_ty(),
|strukt| {
- TyKind::Adt(AdtId(strukt.into()), Substitution::empty(Interner))
- .intern(Interner)
+ Ty::new_adt(self.interner(), strukt.into(), self.types.empty_args)
},
),
- )
- .intern(Interner),
- Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(Interner),
+ Mutability::Not,
+ ),
+ Literal::Char(..) => self.types.char,
Literal::Int(_v, ty) => match ty {
- Some(int_ty) => {
- TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
- .intern(Interner)
- }
+ Some(int_ty) => match int_ty {
+ hir_def::builtin_type::BuiltinInt::Isize => self.types.isize,
+ hir_def::builtin_type::BuiltinInt::I8 => self.types.i8,
+ hir_def::builtin_type::BuiltinInt::I16 => self.types.i16,
+ hir_def::builtin_type::BuiltinInt::I32 => self.types.i32,
+ hir_def::builtin_type::BuiltinInt::I64 => self.types.i64,
+ hir_def::builtin_type::BuiltinInt::I128 => self.types.i128,
+ },
None => {
let expected_ty = expected.to_option(&mut self.table);
tracing::debug!(?expected_ty);
- let opt_ty = match expected_ty.as_ref().map(|it| it.kind(Interner)) {
- Some(TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) => expected_ty,
- Some(TyKind::Scalar(Scalar::Char)) => {
- Some(TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner))
- }
- Some(TyKind::Raw(..) | TyKind::FnDef(..) | TyKind::Function(..)) => {
- Some(TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner))
+ let opt_ty = match expected_ty.as_ref().map(|it| it.kind()) {
+ Some(TyKind::Int(_) | TyKind::Uint(_)) => expected_ty,
+ Some(TyKind::Char) => Some(self.types.u8),
+ Some(TyKind::RawPtr(..) | TyKind::FnDef(..) | TyKind::FnPtr(..)) => {
+ Some(self.types.usize)
}
_ => None,
};
- opt_ty.unwrap_or_else(|| self.table.new_integer_var())
+ opt_ty.unwrap_or_else(|| self.table.next_int_var())
}
},
Literal::Uint(_v, ty) => match ty {
- Some(int_ty) => {
- TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
- .intern(Interner)
- }
+ Some(int_ty) => match int_ty {
+ hir_def::builtin_type::BuiltinUint::Usize => self.types.usize,
+ hir_def::builtin_type::BuiltinUint::U8 => self.types.u8,
+ hir_def::builtin_type::BuiltinUint::U16 => self.types.u16,
+ hir_def::builtin_type::BuiltinUint::U32 => self.types.u32,
+ hir_def::builtin_type::BuiltinUint::U64 => self.types.u64,
+ hir_def::builtin_type::BuiltinUint::U128 => self.types.u128,
+ },
None => {
let expected_ty = expected.to_option(&mut self.table);
- let opt_ty = match expected_ty.as_ref().map(|it| it.kind(Interner)) {
- Some(TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) => expected_ty,
- Some(TyKind::Scalar(Scalar::Char)) => {
- Some(TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner))
- }
- Some(TyKind::Raw(..) | TyKind::FnDef(..) | TyKind::Function(..)) => {
- Some(TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner))
+ let opt_ty = match expected_ty.as_ref().map(|it| it.kind()) {
+ Some(TyKind::Int(_) | TyKind::Uint(_)) => expected_ty,
+ Some(TyKind::Char) => Some(self.types.u8),
+ Some(TyKind::RawPtr(..) | TyKind::FnDef(..) | TyKind::FnPtr(..)) => {
+ Some(self.types.usize)
}
_ => None,
};
- opt_ty.unwrap_or_else(|| self.table.new_integer_var())
+ opt_ty.unwrap_or_else(|| self.table.next_int_var())
}
},
Literal::Float(_v, ty) => match ty {
- Some(float_ty) => {
- TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
- .intern(Interner)
- }
+ Some(float_ty) => match float_ty {
+ hir_def::builtin_type::BuiltinFloat::F16 => self.types.f16,
+ hir_def::builtin_type::BuiltinFloat::F32 => self.types.f32,
+ hir_def::builtin_type::BuiltinFloat::F64 => self.types.f64,
+ hir_def::builtin_type::BuiltinFloat::F128 => self.types.f128,
+ },
None => {
- let opt_ty = expected.to_option(&mut self.table).filter(|ty| {
- matches!(ty.kind(Interner), TyKind::Scalar(Scalar::Float(_)))
- });
- opt_ty.unwrap_or_else(|| self.table.new_float_var())
+ let opt_ty = expected
+ .to_option(&mut self.table)
+ .filter(|ty| matches!(ty.kind(), TyKind::Float(_)));
+ opt_ty.unwrap_or_else(|| self.table.next_float_var())
}
},
},
@@ -1048,13 +983,10 @@ impl<'db> InferenceContext<'db> {
// Underscore expression is an error, we render a specialized diagnostic
// to let the user know what type is expected though.
let expected = expected.to_option(&mut self.table).unwrap_or_else(|| self.err_ty());
- self.push_diagnostic(InferenceDiagnostic::TypedHole {
- expr: tgt_expr,
- expected: expected.clone(),
- });
+ self.push_diagnostic(InferenceDiagnostic::TypedHole { expr: tgt_expr, expected });
expected
}
- Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
+ Expr::OffsetOf(_) => self.types.usize,
Expr::InlineAsm(asm) => {
let check_expr_asm_operand = |this: &mut Self, expr, is_input: bool| {
let ty = this.infer_expr_no_expect(expr, ExprIsRead::Yes);
@@ -1067,27 +999,29 @@ impl<'db> InferenceContext<'db> {
// allows them to be inferred based on how they are used later in the
// function.
if is_input {
- let ty = this.table.structurally_resolve_type(&ty);
- match ty.kind(Interner) {
+ let ty = this.table.structurally_resolve_type(ty);
+ match ty.kind() {
TyKind::FnDef(def, parameters) => {
- let fnptr_ty = TyKind::Function(
- CallableSig::from_def(this.db, *def, parameters).to_fn_ptr(),
- )
- .intern(Interner);
+ let fnptr_ty = Ty::new_fn_ptr(
+ this.interner(),
+ this.interner()
+ .fn_sig(def)
+ .instantiate(this.interner(), parameters),
+ );
_ = this.coerce(
expr.into(),
- ty.to_nextsolver(this.table.interner),
- fnptr_ty.to_nextsolver(this.table.interner),
+ ty,
+ fnptr_ty,
AllowTwoPhase::No,
CoerceNever::Yes,
);
}
- TyKind::Ref(mutbl, _, base_ty) => {
- let ptr_ty = TyKind::Raw(*mutbl, base_ty.clone()).intern(Interner);
+ TyKind::Ref(_, base_ty, mutbl) => {
+ let ptr_ty = Ty::new_ptr(this.interner(), base_ty, mutbl);
_ = this.coerce(
expr.into(),
- ty.to_nextsolver(this.table.interner),
- ptr_ty.to_nextsolver(this.table.interner),
+ ty,
+ ptr_ty,
AllowTwoPhase::No,
CoerceNever::Yes,
);
@@ -1113,7 +1047,7 @@ impl<'db> InferenceContext<'db> {
AsmOperand::Label(expr) => {
self.infer_expr(
expr,
- &Expectation::HasType(self.result.standard_types.unit.clone()),
+ &Expectation::HasType(self.types.unit),
ExprIsRead::No,
);
}
@@ -1123,17 +1057,13 @@ impl<'db> InferenceContext<'db> {
// FIXME: `sym` should report for things that are not functions or statics.
AsmOperand::Sym(_) => (),
});
- if diverge {
- self.result.standard_types.never.clone()
- } else {
- self.result.standard_types.unit.clone()
- }
+ if diverge { self.types.never } else { self.types.unit }
}
};
// use a new type variable if we got unknown here
let ty = self.insert_type_vars_shallow(ty);
- self.write_expr_ty(tgt_expr, ty.clone());
- if self.resolve_ty_shallow(&ty).is_never()
+ self.write_expr_ty(tgt_expr, ty);
+ if self.shallow_resolve(ty).is_never()
&& self.expr_guaranteed_to_constitute_read_for_never(tgt_expr, is_read)
{
// Any expression that produces a value of type `!` must have diverged
@@ -1142,7 +1072,7 @@ impl<'db> InferenceContext<'db> {
ty
}
- fn infer_expr_path(&mut self, path: &Path, id: ExprOrPatId, scope_id: ExprId) -> Ty {
+ fn infer_expr_path(&mut self, path: &Path, id: ExprOrPatId, scope_id: ExprId) -> Ty<'db> {
let g = self.resolver.update_to_inner_scope(self.db, self.owner, scope_id);
let ty = match self.infer_path(path, id) {
Some(ty) => ty,
@@ -1164,32 +1094,24 @@ impl<'db> InferenceContext<'db> {
id: &Option<BlockId>,
statements: &[Statement],
tail: &Option<ExprId>,
- ) -> Ty {
- let ret_ty = self.table.new_type_var();
+ ) -> Ty<'db> {
+ let ret_ty = self.table.next_ty_var();
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
- let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
- let prev_ret_coercion = self
- .return_coercion
- .replace(CoerceMany::new(ret_ty.to_nextsolver(self.table.interner)));
+ let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty);
+ let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(ret_ty));
// FIXME: We should handle async blocks like we handle closures
let expected = &Expectation::has_type(ret_ty);
let (_, inner_ty) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
let ty = this.infer_block(tgt_expr, *id, statements, *tail, None, expected);
if let Some(target) = expected.only_has_type(&mut this.table) {
- match this.coerce(
- tgt_expr.into(),
- ty.to_nextsolver(this.table.interner),
- target.to_nextsolver(this.table.interner),
- AllowTwoPhase::No,
- CoerceNever::Yes,
- ) {
- Ok(res) => res.to_chalk(this.table.interner),
+ match this.coerce(tgt_expr.into(), ty, target, AllowTwoPhase::No, CoerceNever::Yes)
+ {
+ Ok(res) => res,
Err(_) => {
- this.result.type_mismatches.insert(
- tgt_expr.into(),
- TypeMismatch { expected: target.clone(), actual: ty.clone() },
- );
+ this.result
+ .type_mismatches
+ .insert(tgt_expr.into(), TypeMismatch { expected: target, actual: ty });
target
}
}
@@ -1207,57 +1129,67 @@ impl<'db> InferenceContext<'db> {
pub(crate) fn lower_async_block_type_impl_trait(
&mut self,
- inner_ty: Ty,
+ inner_ty: Ty<'db>,
tgt_expr: ExprId,
- ) -> Ty {
+ ) -> Ty<'db> {
// Use the first type parameter as the output type of future.
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, tgt_expr);
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
- TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty)).intern(Interner)
+ Ty::new_alias(
+ self.interner(),
+ AliasTyKind::Opaque,
+ AliasTy::new(
+ self.interner(),
+ opaque_ty_id,
+ GenericArgs::new_from_iter(self.interner(), [inner_ty.into()]),
+ ),
+ )
}
pub(crate) fn write_fn_trait_method_resolution(
&mut self,
fn_x: FnTrait,
- derefed_callee: &Ty,
- adjustments: &mut Vec<Adjustment>,
- callee_ty: &Ty,
- params: &[Ty],
+ derefed_callee: Ty<'db>,
+ adjustments: &mut Vec<Adjustment<'db>>,
+ callee_ty: Ty<'db>,
+ params: &[Ty<'db>],
tgt_expr: ExprId,
) {
match fn_x {
FnTrait::FnOnce | FnTrait::AsyncFnOnce => (),
FnTrait::FnMut | FnTrait::AsyncFnMut => {
- if let TyKind::Ref(Mutability::Mut, lt, inner) = derefed_callee.kind(Interner) {
+ if let TyKind::Ref(lt, inner, Mutability::Mut) = derefed_callee.kind() {
if adjustments
.last()
.map(|it| matches!(it.kind, Adjust::Borrow(_)))
.unwrap_or(true)
{
// prefer reborrow to move
- adjustments
- .push(Adjustment { kind: Adjust::Deref(None), target: inner.clone() });
+ adjustments.push(Adjustment { kind: Adjust::Deref(None), target: inner });
adjustments.push(Adjustment::borrow(
+ self.interner(),
Mutability::Mut,
- inner.clone(),
- lt.clone(),
+ inner,
+ lt,
))
}
} else {
adjustments.push(Adjustment::borrow(
+ self.interner(),
Mutability::Mut,
- derefed_callee.clone(),
- self.table.new_lifetime_var(),
+ derefed_callee,
+ self.table.next_region_var(),
));
}
}
FnTrait::Fn | FnTrait::AsyncFn => {
- if !matches!(derefed_callee.kind(Interner), TyKind::Ref(Mutability::Not, _, _)) {
+ if !matches!(derefed_callee.kind(), TyKind::Ref(_, _, Mutability::Not)) {
adjustments.push(Adjustment::borrow(
+ self.interner(),
Mutability::Not,
- derefed_callee.clone(),
- self.table.new_lifetime_var(),
+ derefed_callee,
+ self.table.next_region_var(),
));
}
}
@@ -1267,57 +1199,48 @@ impl<'db> InferenceContext<'db> {
};
let trait_data = trait_.trait_items(self.db);
if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) {
- let subst = TyBuilder::subst_for_def(self.db, trait_, None)
- .push(callee_ty.clone())
- .push(TyBuilder::tuple_with(params.iter().cloned()))
- .build();
+ let subst = GenericArgs::new_from_iter(
+ self.interner(),
+ [
+ callee_ty.into(),
+ Ty::new_tup_from_iter(self.interner(), params.iter().copied()).into(),
+ ],
+ );
self.write_method_resolution(tgt_expr, func, subst);
}
}
- fn infer_expr_array(
- &mut self,
- array: &Array,
- expected: &Expectation,
- ) -> chalk_ir::Ty<Interner> {
- let elem_ty = match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(Interner)) {
- Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st.clone(),
- _ => self.table.new_type_var(),
+ fn infer_expr_array(&mut self, array: &Array, expected: &Expectation<'db>) -> Ty<'db> {
+ let elem_ty = match expected.to_option(&mut self.table).as_ref().map(|t| t.kind()) {
+ Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st,
+ _ => self.table.next_ty_var(),
};
let krate = self.resolver.krate();
- let expected = Expectation::has_type(elem_ty.clone());
+ let expected = Expectation::has_type(elem_ty);
let (elem_ty, len) = match array {
Array::ElementList { elements, .. } if elements.is_empty() => {
- (elem_ty, consteval::usize_const(self.db, Some(0), krate))
+ (elem_ty, consteval_nextsolver::usize_const(self.db, Some(0), krate))
}
Array::ElementList { elements, .. } => {
- let mut coerce = CoerceMany::with_coercion_sites(
- elem_ty.to_nextsolver(self.table.interner),
- elements,
- );
+ let mut coerce = CoerceMany::with_coercion_sites(elem_ty, elements);
for &expr in elements.iter() {
let cur_elem_ty = self.infer_expr_inner(expr, &expected, ExprIsRead::Yes);
- coerce.coerce(
- self,
- &ObligationCause::new(),
- expr,
- cur_elem_ty.to_nextsolver(self.table.interner),
- );
+ coerce.coerce(self, &ObligationCause::new(), expr, cur_elem_ty);
}
(
- coerce.complete(self).to_chalk(self.table.interner),
- consteval::usize_const(self.db, Some(elements.len() as u128), krate),
+ coerce.complete(self),
+ consteval_nextsolver::usize_const(self.db, Some(elements.len() as u128), krate),
)
}
&Array::Repeat { initializer, repeat } => {
self.infer_expr_coerce(
initializer,
- &Expectation::has_type(elem_ty.clone()),
+ &Expectation::has_type(elem_ty),
ExprIsRead::Yes,
);
- let usize = TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner);
+ let usize = self.types.usize;
match self.body[repeat] {
Expr::Underscore => {
self.write_expr_ty(repeat, usize);
@@ -1325,20 +1248,12 @@ impl<'db> InferenceContext<'db> {
_ => _ = self.infer_expr(repeat, &Expectation::HasType(usize), ExprIsRead::Yes),
}
- (
- elem_ty,
- consteval::eval_to_const(
- repeat,
- ParamLoweringMode::Placeholder,
- self,
- DebruijnIndex::INNERMOST,
- ),
- )
+ (elem_ty, consteval_nextsolver::eval_to_const(repeat, self))
}
};
// Try to evaluate unevaluated constant, and insert variable if is not possible.
let len = self.table.insert_const_vars_shallow(len);
- TyKind::Array(elem_ty, len).intern(Interner)
+ Ty::new_array_with_const_len(self.interner(), elem_ty, len)
}
pub(super) fn infer_return(&mut self, expr: ExprId) {
@@ -1346,21 +1261,15 @@ impl<'db> InferenceContext<'db> {
.return_coercion
.as_mut()
.expect("infer_return called outside function body")
- .expected_ty()
- .to_chalk(self.table.interner);
+ .expected_ty();
let return_expr_ty =
self.infer_expr_inner(expr, &Expectation::HasType(ret_ty), ExprIsRead::Yes);
let mut coerce_many = self.return_coercion.take().unwrap();
- coerce_many.coerce(
- self,
- &ObligationCause::new(),
- expr,
- return_expr_ty.to_nextsolver(self.table.interner),
- );
+ coerce_many.coerce(self, &ObligationCause::new(), expr, return_expr_ty);
self.return_coercion = Some(coerce_many);
}
- fn infer_expr_return(&mut self, ret: ExprId, expr: Option<ExprId>) -> Ty {
+ fn infer_expr_return(&mut self, ret: ExprId, expr: Option<ExprId>) -> Ty<'db> {
match self.return_coercion {
Some(_) => {
if let Some(expr) = expr {
@@ -1378,23 +1287,20 @@ impl<'db> InferenceContext<'db> {
}
}
}
- self.result.standard_types.never.clone()
+ self.types.never
}
- fn infer_expr_become(&mut self, expr: ExprId) -> Ty {
+ fn infer_expr_become(&mut self, expr: ExprId) -> Ty<'db> {
match &self.return_coercion {
Some(return_coercion) => {
- let ret_ty = return_coercion.expected_ty().to_chalk(self.table.interner);
+ let ret_ty = return_coercion.expected_ty();
- let call_expr_ty = self.infer_expr_inner(
- expr,
- &Expectation::HasType(ret_ty.clone()),
- ExprIsRead::Yes,
- );
+ let call_expr_ty =
+ self.infer_expr_inner(expr, &Expectation::HasType(ret_ty), ExprIsRead::Yes);
// NB: this should *not* coerce.
// tail calls don't support any coercions except lifetimes ones (like `&'static u8 -> &'a u8`).
- self.unify(&call_expr_ty, &ret_ty);
+ self.unify(call_expr_ty, ret_ty);
}
None => {
// FIXME: diagnose `become` outside of functions
@@ -1402,10 +1308,10 @@ impl<'db> InferenceContext<'db> {
}
}
- self.result.standard_types.never.clone()
+ self.types.never
}
- fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation) -> Ty {
+ fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation<'db>) -> Ty<'db> {
if let Some(box_id) = self.resolve_boxed_box() {
let table = &mut self.table;
let inner_exp = expected
@@ -1414,16 +1320,22 @@ impl<'db> InferenceContext<'db> {
.and_then(|e| e.as_adt())
.filter(|(e_adt, _)| e_adt == &box_id)
.map(|(_, subts)| {
- let g = subts.at(Interner, 0);
- Expectation::rvalue_hint(self, Ty::clone(g.assert_ty_ref(Interner)))
+ let g = subts.type_at(0);
+ Expectation::rvalue_hint(self, g)
})
.unwrap_or_else(Expectation::none);
let inner_ty = self.infer_expr_inner(inner_expr, &inner_exp, ExprIsRead::Yes);
- TyBuilder::adt(self.db, box_id)
- .push(inner_ty)
- .fill_with_defaults(self.db, || self.table.new_type_var())
- .build()
+ Ty::new_adt(
+ self.interner(),
+ box_id,
+ GenericArgs::fill_with_defaults(
+ self.interner(),
+ box_id.into(),
+ [inner_ty.into()],
+ |_, _, id, _| self.table.next_var_for_param(id),
+ ),
+ )
} else {
self.err_ty()
}
@@ -1435,7 +1347,7 @@ impl<'db> InferenceContext<'db> {
op: BinaryOp,
rhs: ExprId,
tgt_expr: ExprId,
- ) -> Ty {
+ ) -> Ty<'db> {
let lhs_expectation = Expectation::none();
let is_read = if matches!(op, BinaryOp::Assignment { .. }) {
ExprIsRead::Yes
@@ -1443,24 +1355,24 @@ impl<'db> InferenceContext<'db> {
ExprIsRead::No
};
let lhs_ty = self.infer_expr(lhs, &lhs_expectation, is_read);
- let rhs_ty = self.table.new_type_var();
+ let rhs_ty = self.table.next_ty_var();
let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
let func = trait_id.trait_items(self.db).method_by_name(&name)?;
Some((trait_id, func))
});
- let (trait_, func) = match trait_func {
- Some(it) => it,
+ let func = match trait_func {
+ Some((_, it)) => it,
None => {
// HACK: `rhs_ty` is a general inference variable with no clue at all at this
// point. Passing `lhs_ty` as both operands just to check if `lhs_ty` is a builtin
// type applicable to `op`.
- let ret_ty = if self.is_builtin_binop(&lhs_ty, &lhs_ty, op) {
+ let ret_ty = if self.is_builtin_binop(lhs_ty, lhs_ty, op) {
// Assume both operands are builtin so we can continue inference. No guarantee
// on the correctness, rustc would complain as necessary lang items don't seem
// to exist anyway.
- self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op)
+ self.enforce_builtin_binop_types(lhs_ty, rhs_ty, op)
} else {
self.err_ty()
};
@@ -1473,59 +1385,53 @@ impl<'db> InferenceContext<'db> {
// HACK: We can use this substitution for the function because the function itself doesn't
// have its own generic parameters.
- let subst = TyBuilder::subst_for_def(self.db, trait_, None);
- if subst.remaining() != 2 {
- return Ty::new(Interner, TyKind::Error);
- }
- let subst = subst.push(lhs_ty.clone()).push(rhs_ty.clone()).build();
+ let args = GenericArgs::new_from_iter(self.interner(), [lhs_ty.into(), rhs_ty.into()]);
- self.write_method_resolution(tgt_expr, func, subst.clone());
+ self.write_method_resolution(tgt_expr, func, args);
- let interner = DbInterner::new_with(self.db, None, None);
- let args: crate::next_solver::GenericArgs<'_> = subst.to_nextsolver(interner);
- let method_ty =
- self.db.value_ty(func.into()).unwrap().instantiate(interner, args).to_chalk(interner);
- self.register_obligations_for_call(&method_ty);
+ let method_ty = self.db.value_ty(func.into()).unwrap().instantiate(self.interner(), args);
+ self.register_obligations_for_call(method_ty);
- self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone()), ExprIsRead::Yes);
+ self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty), ExprIsRead::Yes);
- let ret_ty = match method_ty.callable_sig(self.db) {
+ let ret_ty = match method_ty.callable_sig(self.interner()) {
Some(sig) => {
- let p_left = &sig.params()[0];
+ let sig = sig.skip_binder();
+ let p_left = sig.inputs_and_output.as_slice()[0];
if matches!(op, BinaryOp::CmpOp(..) | BinaryOp::Assignment { .. })
- && let TyKind::Ref(mtbl, lt, _) = p_left.kind(Interner)
+ && let TyKind::Ref(lt, _, mtbl) = p_left.kind()
{
self.write_expr_adj(
lhs,
Box::new([Adjustment {
- kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
- target: p_left.clone(),
+ kind: Adjust::Borrow(AutoBorrow::Ref(lt, mtbl)),
+ target: p_left,
}]),
);
}
- let p_right = &sig.params()[1];
+ let p_right = sig.inputs_and_output.as_slice()[1];
if matches!(op, BinaryOp::CmpOp(..))
- && let TyKind::Ref(mtbl, lt, _) = p_right.kind(Interner)
+ && let TyKind::Ref(lt, _, mtbl) = p_right.kind()
{
self.write_expr_adj(
rhs,
Box::new([Adjustment {
- kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
- target: p_right.clone(),
+ kind: Adjust::Borrow(AutoBorrow::Ref(lt, mtbl)),
+ target: p_right,
}]),
);
}
- sig.ret().clone()
+ sig.output()
}
None => self.err_ty(),
};
let ret_ty = self.process_remote_user_written_ty(ret_ty);
- if self.is_builtin_binop(&lhs_ty, &rhs_ty, op) {
+ if self.is_builtin_binop(lhs_ty, rhs_ty, op) {
// use knowledge of built-in binary ops, which can sometimes help inference
- let builtin_ret = self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op);
- self.unify(&builtin_ret, &ret_ty);
+ let builtin_ret = self.enforce_builtin_binop_types(lhs_ty, rhs_ty, op);
+ self.unify(builtin_ret, ret_ty);
builtin_ret
} else {
ret_ty
@@ -1539,8 +1445,8 @@ impl<'db> InferenceContext<'db> {
statements: &[Statement],
tail: Option<ExprId>,
label: Option<LabelId>,
- expected: &Expectation,
- ) -> Ty {
+ expected: &Expectation<'db>,
+ ) -> Ty<'db> {
let coerce_ty = expected.coercion_target_type(&mut self.table);
let g = self.resolver.update_to_inner_scope(self.db, self.owner, expr);
let prev_env = block_id.map(|block_id| {
@@ -1557,7 +1463,7 @@ impl<'db> InferenceContext<'db> {
let decl_ty = type_ref
.as_ref()
.map(|&tr| this.make_body_ty(tr))
- .unwrap_or_else(|| this.table.new_type_var());
+ .unwrap_or_else(|| this.table.next_ty_var());
let ty = if let Some(expr) = initializer {
// If we have a subpattern that performs a read, we want to consider this
@@ -1571,13 +1477,13 @@ impl<'db> InferenceContext<'db> {
let ty = if contains_explicit_ref_binding(this.body, *pat) {
this.infer_expr(
*expr,
- &Expectation::has_type(decl_ty.clone()),
+ &Expectation::has_type(decl_ty),
target_is_read,
)
} else {
this.infer_expr_coerce(
*expr,
- &Expectation::has_type(decl_ty.clone()),
+ &Expectation::has_type(decl_ty),
target_is_read,
)
};
@@ -1590,13 +1496,13 @@ impl<'db> InferenceContext<'db> {
origin: DeclOrigin::LocalDecl { has_else: else_branch.is_some() },
};
- this.infer_top_pat(*pat, &ty, Some(decl));
+ this.infer_top_pat(*pat, ty, Some(decl));
if let Some(expr) = else_branch {
let previous_diverges =
mem::replace(&mut this.diverges, Diverges::Maybe);
this.infer_expr_coerce(
*expr,
- &Expectation::HasType(this.result.standard_types.never.clone()),
+ &Expectation::HasType(this.types.never),
ExprIsRead::Yes,
);
this.diverges = previous_diverges;
@@ -1608,7 +1514,7 @@ impl<'db> InferenceContext<'db> {
} else {
this.infer_expr_coerce(
expr,
- &Expectation::HasType(this.result.standard_types.unit.clone()),
+ &Expectation::HasType(this.types.unit),
ExprIsRead::Yes,
);
}
@@ -1642,8 +1548,8 @@ impl<'db> InferenceContext<'db> {
if this
.coerce(
expr.into(),
- this.result.standard_types.unit.to_nextsolver(this.table.interner),
- t.to_nextsolver(this.table.interner),
+ this.types.unit,
+ t,
AllowTwoPhase::No,
coerce_never,
)
@@ -1651,15 +1557,12 @@ impl<'db> InferenceContext<'db> {
{
this.result.type_mismatches.insert(
expr.into(),
- TypeMismatch {
- expected: t.clone(),
- actual: this.result.standard_types.unit.clone(),
- },
+ TypeMismatch { expected: t, actual: this.types.unit },
);
}
t
} else {
- this.result.standard_types.unit.clone()
+ this.types.unit
}
}
});
@@ -1673,32 +1576,30 @@ impl<'db> InferenceContext<'db> {
fn lookup_field(
&mut self,
- receiver_ty: &Ty,
+ receiver_ty: Ty<'db>,
name: &Name,
- ) -> Option<(Ty, Either<FieldId, TupleFieldId>, Vec<Adjustment>, bool)> {
- let interner = self.table.interner;
- let mut autoderef = self.table.autoderef(receiver_ty.to_nextsolver(self.table.interner));
+ ) -> Option<(Ty<'db>, Either<FieldId, TupleFieldId>, Vec<Adjustment<'db>>, bool)> {
+ let interner = self.interner();
+ let mut autoderef = self.table.autoderef(receiver_ty);
let mut private_field = None;
let res = autoderef.by_ref().find_map(|(derefed_ty, _)| {
let (field_id, parameters) = match derefed_ty.kind() {
- crate::next_solver::TyKind::Tuple(substs) => {
+ TyKind::Tuple(substs) => {
return name.as_tuple_index().and_then(|idx| {
substs.as_slice().get(idx).copied().map(|ty| {
(
Either::Right(TupleFieldId {
tuple: TupleId(
- self.tuple_field_accesses_rev
- .insert_full(substs.to_chalk(interner))
- .0 as u32,
+ self.tuple_field_accesses_rev.insert_full(substs).0 as u32,
),
index: idx as u32,
}),
- ty.to_chalk(interner),
+ ty,
)
})
});
}
- crate::next_solver::TyKind::Adt(adt, parameters) => match adt.def_id().0 {
+ TyKind::Adt(adt, parameters) => match adt.def_id().0 {
hir_def::AdtId::StructId(s) => {
let local_id = s.fields(self.db).field(name)?;
let field = FieldId { parent: s.into(), local_id };
@@ -1713,18 +1614,16 @@ impl<'db> InferenceContext<'db> {
},
_ => return None,
};
- let parameters: crate::Substitution = parameters.to_chalk(interner);
let is_visible = self.db.field_visibilities(field_id.parent)[field_id.local_id]
.is_visible_from(self.db, self.resolver.module());
if !is_visible {
if private_field.is_none() {
- private_field = Some((field_id, parameters.clone()));
+ private_field = Some((field_id, parameters));
}
return None;
}
- let ty = self.db.field_types(field_id.parent)[field_id.local_id]
- .clone()
- .substitute(Interner, &parameters);
+ let ty = self.db.field_types_ns(field_id.parent)[field_id.local_id]
+ .instantiate(interner, parameters);
Some((Either::Left(field_id), ty))
});
@@ -1738,9 +1637,8 @@ impl<'db> InferenceContext<'db> {
None => {
let (field_id, subst) = private_field?;
let adjustments = autoderef.adjust_steps();
- let ty = self.db.field_types(field_id.parent)[field_id.local_id]
- .clone()
- .substitute(Interner, &subst);
+ let ty = self.db.field_types_ns(field_id.parent)[field_id.local_id]
+ .instantiate(self.interner(), subst);
let ty = self.process_remote_user_written_ty(ty);
(ty, Either::Left(field_id), adjustments, false)
@@ -1753,8 +1651,8 @@ impl<'db> InferenceContext<'db> {
tgt_expr: ExprId,
receiver: ExprId,
name: &Name,
- expected: &Expectation,
- ) -> Ty {
+ expected: &Expectation<'db>,
+ ) -> Ty<'db> {
// Field projections don't constitute reads.
let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::No);
@@ -1764,7 +1662,7 @@ impl<'db> InferenceContext<'db> {
return self.err_ty();
}
- match self.lookup_field(&receiver_ty, name) {
+ match self.lookup_field(receiver_ty, name) {
Some((ty, field_id, adjustments, is_public)) => {
self.write_expr_adj(receiver, adjustments.into_boxed_slice());
self.result.field_resolutions.insert(tgt_expr, field_id);
@@ -1780,8 +1678,7 @@ impl<'db> InferenceContext<'db> {
None => {
// no field found, lets attempt to resolve it like a function so that IDE things
// work out while people are typing
- let canonicalized_receiver =
- self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner));
+ let canonicalized_receiver = self.canonicalize(receiver_ty);
let resolved = method_resolution::lookup_method(
self.db,
&canonicalized_receiver,
@@ -1792,28 +1689,24 @@ impl<'db> InferenceContext<'db> {
);
self.push_diagnostic(InferenceDiagnostic::UnresolvedField {
expr: tgt_expr,
- receiver: receiver_ty.clone(),
+ receiver: receiver_ty,
name: name.clone(),
method_with_same_name_exists: resolved.is_some(),
});
match resolved {
Some((adjust, func, _)) => {
let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty);
- let substs = self.substs_for_method_call(tgt_expr, func.into(), None);
+ let args = self.substs_for_method_call(tgt_expr, func.into(), None);
self.write_expr_adj(receiver, adjustments.into_boxed_slice());
- self.write_method_resolution(tgt_expr, func, substs.clone());
+ self.write_method_resolution(tgt_expr, func, args);
- let interner = DbInterner::new_with(self.db, None, None);
- let args: crate::next_solver::GenericArgs<'_> =
- substs.to_nextsolver(interner);
self.check_method_call(
tgt_expr,
&[],
self.db
.value_ty(func.into())
.unwrap()
- .instantiate(interner, args)
- .to_chalk(interner),
+ .instantiate(self.interner(), args),
ty,
expected,
)
@@ -1829,47 +1722,42 @@ impl<'db> InferenceContext<'db> {
tgt_expr: ExprId,
callee: ExprId,
args: &[ExprId],
- expected: &Expectation,
- ) -> Ty {
+ expected: &Expectation<'db>,
+ ) -> Ty<'db> {
let callee_ty = self.infer_expr(callee, &Expectation::none(), ExprIsRead::Yes);
- let interner = self.table.interner;
- let mut derefs = self.table.autoderef(callee_ty.to_nextsolver(interner));
+ let interner = self.interner();
+ let mut derefs = self.table.autoderef(callee_ty);
let (res, derefed_callee) = loop {
let Some((callee_deref_ty, _)) = derefs.next() else {
- break (None, callee_ty.clone());
+ break (None, callee_ty);
};
- let callee_deref_ty = callee_deref_ty.to_chalk(interner);
- if let Some(res) = derefs.table.callable_sig(&callee_deref_ty, args.len()) {
+ if let Some(res) = derefs.table.callable_sig(callee_deref_ty, args.len()) {
break (Some(res), callee_deref_ty);
}
};
// if the function is unresolved, we use is_varargs=true to
// suppress the arg count diagnostic here
- let is_varargs =
- derefed_callee.callable_sig(self.db).is_some_and(|sig| sig.is_varargs) || res.is_none();
+ let is_varargs = derefed_callee.callable_sig(interner).is_some_and(|sig| sig.c_variadic())
+ || res.is_none();
let (param_tys, ret_ty) = match res {
Some((func, params, ret_ty)) => {
- let params_chalk =
- params.iter().map(|param| param.to_chalk(interner)).collect::<Vec<_>>();
let mut adjustments = derefs.adjust_steps();
if let Some(fn_x) = func {
self.write_fn_trait_method_resolution(
fn_x,
- &derefed_callee,
+ derefed_callee,
&mut adjustments,
- &callee_ty,
- &params_chalk,
+ callee_ty,
+ &params,
tgt_expr,
);
}
- if let &TyKind::Closure(c, _) =
- self.table.resolve_completely(callee_ty.clone()).kind(Interner)
- {
+ if let TyKind::Closure(c, _) = self.table.resolve_completely(callee_ty).kind() {
self.add_current_closure_dependency(c.into());
self.deferred_closures.entry(c.into()).or_default().push((
- derefed_callee.clone(),
- callee_ty.clone(),
- params_chalk,
+ derefed_callee,
+ callee_ty,
+ params.clone(),
tgt_expr,
));
}
@@ -1879,9 +1767,9 @@ impl<'db> InferenceContext<'db> {
None => {
self.push_diagnostic(InferenceDiagnostic::ExpectedFunction {
call_expr: tgt_expr,
- found: callee_ty.clone(),
+ found: callee_ty,
});
- (Vec::new(), crate::next_solver::Ty::new_error(interner, ErrorGuaranteed))
+ (Vec::new(), Ty::new_error(interner, ErrorGuaranteed))
}
};
let indices_to_skip = self.check_legacy_const_generics(derefed_callee, args);
@@ -1901,14 +1789,14 @@ impl<'db> InferenceContext<'db> {
&mut self,
tgt_expr: ExprId,
args: &[ExprId],
- callee_ty: Ty,
- param_tys: &[crate::next_solver::Ty<'db>],
- ret_ty: crate::next_solver::Ty<'db>,
+ callee_ty: Ty<'db>,
+ param_tys: &[Ty<'db>],
+ ret_ty: Ty<'db>,
indices_to_skip: &[u32],
is_varargs: bool,
- expected: &Expectation,
- ) -> Ty {
- self.register_obligations_for_call(&callee_ty);
+ expected: &Expectation<'db>,
+ ) -> Ty<'db> {
+ self.register_obligations_for_call(callee_ty);
self.check_call_arguments(
tgt_expr,
@@ -1919,7 +1807,7 @@ impl<'db> InferenceContext<'db> {
indices_to_skip,
is_varargs,
);
- self.table.normalize_associated_types_in_ns(ret_ty).to_chalk(self.table.interner)
+ self.table.normalize_associated_types_in(ret_ty)
}
fn infer_method_call(
@@ -1928,16 +1816,13 @@ impl<'db> InferenceContext<'db> {
receiver: ExprId,
args: &[ExprId],
method_name: &Name,
- generic_args: Option<&GenericArgs>,
- expected: &Expectation,
- ) -> Ty {
+ generic_args: Option<&HirGenericArgs>,
+ expected: &Expectation<'db>,
+ ) -> Ty<'db> {
let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::Yes);
- let receiver_ty = self.table.structurally_resolve_type(&receiver_ty);
+ let receiver_ty = self.table.try_structurally_resolve_type(receiver_ty);
- if matches!(
- receiver_ty.kind(Interner),
- TyKind::Error | TyKind::InferenceVar(_, TyVariableKind::General)
- ) {
+ if matches!(receiver_ty.kind(), TyKind::Error(_) | TyKind::Infer(InferTy::TyVar(_))) {
// Don't probe on error type, or on a fully unresolved infer var.
// FIXME: Emit an error if we're probing on an infer var (type annotations needed).
for &arg in args {
@@ -1947,8 +1832,7 @@ impl<'db> InferenceContext<'db> {
return receiver_ty;
}
- let canonicalized_receiver =
- self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner));
+ let canonicalized_receiver = self.canonicalize(receiver_ty);
let resolved = method_resolution::lookup_method(
self.db,
@@ -1970,18 +1854,16 @@ impl<'db> InferenceContext<'db> {
let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty);
self.write_expr_adj(receiver, adjustments.into_boxed_slice());
- let substs = self.substs_for_method_call(tgt_expr, func.into(), generic_args);
- self.write_method_resolution(tgt_expr, func, substs.clone());
+ let gen_args = self.substs_for_method_call(tgt_expr, func.into(), generic_args);
+ self.write_method_resolution(tgt_expr, func, gen_args);
let interner = DbInterner::new_with(self.db, None, None);
- let gen_args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
self.check_method_call(
tgt_expr,
args,
self.db
.value_ty(func.into())
.expect("we have a function def")
- .instantiate(interner, gen_args)
- .to_chalk(interner),
+ .instantiate(interner, gen_args),
ty,
expected,
)
@@ -1989,7 +1871,7 @@ impl<'db> InferenceContext<'db> {
// Failed to resolve, report diagnostic and try to resolve as call to field access or
// assoc function
None => {
- let field_with_same_name_exists = match self.lookup_field(&receiver_ty, method_name)
+ let field_with_same_name_exists = match self.lookup_field(receiver_ty, method_name)
{
Some((ty, field_id, adjustments, _public)) => {
self.write_expr_adj(receiver, adjustments.into_boxed_slice());
@@ -2017,48 +1899,46 @@ impl<'db> InferenceContext<'db> {
self.push_diagnostic(InferenceDiagnostic::UnresolvedMethodCall {
expr: tgt_expr,
- receiver: receiver_ty.clone(),
+ receiver: receiver_ty,
name: method_name.clone(),
- field_with_same_name: field_with_same_name_exists.clone(),
+ field_with_same_name: field_with_same_name_exists,
assoc_func_with_same_name,
});
let recovered = match assoc_func_with_same_name {
Some(f) => {
- let substs = self.substs_for_method_call(tgt_expr, f.into(), generic_args);
+ let args = self.substs_for_method_call(tgt_expr, f.into(), generic_args);
let interner = DbInterner::new_with(self.db, None, None);
- let args: crate::next_solver::GenericArgs<'_> =
- substs.to_nextsolver(interner);
let f = self
.db
.value_ty(f.into())
.expect("we have a function def")
- .instantiate(interner, args)
- .to_chalk(interner);
- let sig = f.callable_sig(self.db).expect("we have a function def");
+ .instantiate(interner, args);
+ let sig = f.callable_sig(self.interner()).expect("we have a function def");
Some((f, sig, true))
}
None => field_with_same_name_exists.and_then(|field_ty| {
- let callable_sig = field_ty.callable_sig(self.db)?;
+ let callable_sig = field_ty.callable_sig(self.interner())?;
Some((field_ty, callable_sig, false))
}),
};
match recovered {
- Some((callee_ty, sig, strip_first)) => self.check_call(
- tgt_expr,
- args,
- callee_ty,
- &sig.params()
- .get(strip_first as usize..)
- .unwrap_or(&[])
- .iter()
- .map(|param| param.to_nextsolver(self.table.interner))
- .collect::<Vec<_>>(),
- sig.ret().to_nextsolver(self.table.interner),
- &[],
- true,
- expected,
- ),
+ Some((callee_ty, sig, strip_first)) => {
+ let sig = sig.skip_binder();
+ self.check_call(
+ tgt_expr,
+ args,
+ callee_ty,
+ sig.inputs_and_output
+ .inputs()
+ .get(strip_first as usize..)
+ .unwrap_or(&[]),
+ sig.output(),
+ &[],
+ true,
+ expected,
+ )
+ }
None => {
for &arg in args.iter() {
self.infer_expr_no_expect(arg, ExprIsRead::Yes);
@@ -2074,39 +1954,38 @@ impl<'db> InferenceContext<'db> {
&mut self,
tgt_expr: ExprId,
args: &[ExprId],
- method_ty: Ty,
- receiver_ty: Ty,
- expected: &Expectation,
- ) -> Ty {
- self.register_obligations_for_call(&method_ty);
- let interner = self.table.interner;
+ method_ty: Ty<'db>,
+ receiver_ty: Ty<'db>,
+ expected: &Expectation<'db>,
+ ) -> Ty<'db> {
+ self.register_obligations_for_call(method_ty);
let ((formal_receiver_ty, param_tys), ret_ty, is_varargs) =
- match method_ty.callable_sig(self.db) {
- Some(sig) => (
- if !sig.params().is_empty() {
- (
- sig.params()[0].to_nextsolver(interner),
- sig.params()[1..]
- .iter()
- .map(|param| param.to_nextsolver(interner))
- .collect(),
- )
- } else {
- (crate::next_solver::Ty::new_error(interner, ErrorGuaranteed), Vec::new())
- },
- sig.ret().to_nextsolver(interner),
- sig.is_varargs,
- ),
+ match method_ty.callable_sig(self.interner()) {
+ Some(sig) => {
+ let sig = sig.skip_binder();
+ (
+ if !sig.inputs_and_output.inputs().is_empty() {
+ (
+ sig.inputs_and_output.as_slice()[0],
+ sig.inputs_and_output.inputs()[1..].to_vec(),
+ )
+ } else {
+ (self.types.error, Vec::new())
+ },
+ sig.output(),
+ sig.c_variadic,
+ )
+ }
None => {
let formal_receiver_ty = self.table.next_ty_var();
let ret_ty = self.table.next_ty_var();
((formal_receiver_ty, Vec::new()), ret_ty, true)
}
};
- self.table.unify_ns(formal_receiver_ty, receiver_ty.to_nextsolver(interner));
+ self.table.unify(formal_receiver_ty, receiver_ty);
self.check_call_arguments(tgt_expr, &param_tys, ret_ty, expected, args, &[], is_varargs);
- self.table.normalize_associated_types_in_ns(ret_ty).to_chalk(interner)
+ self.table.normalize_associated_types_in(ret_ty)
}
/// Generic function that factors out common logic from function calls,
@@ -2115,18 +1994,16 @@ impl<'db> InferenceContext<'db> {
&mut self,
call_expr: ExprId,
// Types (as defined in the *signature* of the target function)
- formal_input_tys: &[crate::next_solver::Ty<'db>],
- formal_output: crate::next_solver::Ty<'db>,
+ formal_input_tys: &[Ty<'db>],
+ formal_output: Ty<'db>,
// Expected output from the parent expression or statement
- expectation: &Expectation,
+ expectation: &Expectation<'db>,
// The expressions for each provided argument
provided_args: &[ExprId],
skip_indices: &[u32],
// Whether the function is variadic, for example when imported from C
c_variadic: bool,
) {
- let interner = self.table.interner;
-
// First, let's unify the formal method signature with the expectation eagerly.
// We use this to guide coercion inference; it's output is "fudged" which means
// any remaining type variables are assigned to new, unrelated variables. This
@@ -2145,14 +2022,9 @@ impl<'db> InferenceContext<'db> {
// is polymorphic) and the expected return type.
// No argument expectations are produced if unification fails.
let origin = ObligationCause::new();
- ocx.sup(
- &origin,
- self.table.trait_env.env,
- expected_output.to_nextsolver(interner),
- formal_output,
- )?;
+ ocx.sup(&origin, self.table.trait_env.env, expected_output, formal_output)?;
if !ocx.select_where_possible().is_empty() {
- return Err(crate::next_solver::TypeError::Mismatch);
+ return Err(TypeError::Mismatch);
}
// Record all the argument types, with the args
@@ -2200,9 +2072,9 @@ impl<'db> InferenceContext<'db> {
// We introduce a helper function to demand that a given argument satisfy a given input
// This is more complicated than just checking type equality, as arguments could be coerced
// This version writes those types back so further type checking uses the narrowed types
- let demand_compatible = |this: &mut InferenceContext<'db>, idx| {
- let formal_input_ty: crate::next_solver::Ty<'db> = formal_input_tys[idx];
- let expected_input_ty: crate::next_solver::Ty<'db> = expected_input_tys[idx];
+ let demand_compatible = |this: &mut InferenceContext<'_, 'db>, idx| {
+ let formal_input_ty: Ty<'db> = formal_input_tys[idx];
+ let expected_input_ty: Ty<'db> = expected_input_tys[idx];
let provided_arg = provided_args[idx];
debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
@@ -2210,19 +2082,14 @@ impl<'db> InferenceContext<'db> {
// We're on the happy path here, so we'll do a more involved check and write back types
// To check compatibility, we'll do 3 things:
// 1. Unify the provided argument with the expected type
- let expectation = Expectation::rvalue_hint(this, expected_input_ty.to_chalk(interner));
+ let expectation = Expectation::rvalue_hint(this, expected_input_ty);
- let checked_ty = this
- .infer_expr_inner(provided_arg, &expectation, ExprIsRead::Yes)
- .to_nextsolver(interner);
+ let checked_ty = this.infer_expr_inner(provided_arg, &expectation, ExprIsRead::Yes);
// 2. Coerce to the most detailed type that could be coerced
// to, which is `expected_ty` if `rvalue_hint` returns an
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
- let coerced_ty = expectation
- .only_has_type(&mut this.table)
- .map(|it| it.to_nextsolver(interner))
- .unwrap_or(formal_input_ty);
+ let coerced_ty = expectation.only_has_type(&mut this.table).unwrap_or(formal_input_ty);
// Cause selection errors caused by resolving a single argument to point at the
// argument and not the call. This lets us customize the span pointed to in the
@@ -2259,7 +2126,7 @@ impl<'db> InferenceContext<'db> {
// If neither check failed, the types are compatible
match formal_ty_error {
- Ok(crate::next_solver::infer::InferOk { obligations, value: () }) => {
+ Ok(InferOk { obligations, value: () }) => {
this.table.register_predicates(obligations);
Ok(())
}
@@ -2313,13 +2180,9 @@ impl<'db> InferenceContext<'db> {
&& args_count_matches
{
// Don't report type mismatches if there is a mismatch in args count.
- self.result.type_mismatches.insert(
- (*arg).into(),
- TypeMismatch {
- expected: expected.to_chalk(interner),
- actual: found.to_chalk(interner),
- },
- );
+ self.result
+ .type_mismatches
+ .insert((*arg).into(), TypeMismatch { expected, actual: found });
}
}
}
@@ -2331,14 +2194,14 @@ impl<'db> InferenceContext<'db> {
&mut self,
expr: ExprId,
def: GenericDefId,
- generic_args: Option<&GenericArgs>,
- ) -> Substitution {
- struct LowererCtx<'a, 'b> {
- ctx: &'a mut InferenceContext<'b>,
+ generic_args: Option<&HirGenericArgs>,
+ ) -> GenericArgs<'db> {
+ struct LowererCtx<'a, 'b, 'db> {
+ ctx: &'a mut InferenceContext<'b, 'db>,
expr: ExprId,
}
- impl GenericArgsLowerer for LowererCtx<'_, '_> {
+ impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, 'db> {
fn report_len_mismatch(
&mut self,
def: GenericDefId,
@@ -2373,21 +2236,22 @@ impl<'db> InferenceContext<'db> {
&mut self,
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::GenericArg {
+ arg: &HirGenericArg,
+ ) -> GenericArg<'db> {
match (param, arg) {
- (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => {
- self.ctx.make_body_lifetime(*lifetime).cast(Interner)
+ (
+ GenericParamDataRef::LifetimeParamData(_),
+ HirGenericArg::Lifetime(lifetime),
+ ) => self.ctx.make_body_lifetime(*lifetime).into(),
+ (GenericParamDataRef::TypeParamData(_), HirGenericArg::Type(type_ref)) => {
+ self.ctx.make_body_ty(*type_ref).into()
}
- (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => {
- self.ctx.make_body_ty(*type_ref).cast(Interner)
- }
- (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");
};
- let const_ty = self.ctx.db.const_param_ty(const_id);
- self.ctx.make_body_const(*konst, const_ty).cast(Interner)
+ let const_ty = self.ctx.db.const_param_ty_ns(const_id);
+ self.ctx.make_body_const(*konst, const_ty).into()
}
_ => unreachable!("unmatching param kinds were passed to `provided_kind()`"),
}
@@ -2395,12 +2259,12 @@ impl<'db> InferenceContext<'db> {
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.make_path_as_body_const(path, const_ty),
- TypeLikeConst::Infer => self.ctx.table.new_const_var(const_ty),
+ TypeLikeConst::Infer => self.ctx.table.next_const_var(),
}
}
@@ -2410,35 +2274,15 @@ impl<'db> InferenceContext<'db> {
param_id: GenericParamId,
_param: GenericParamDataRef<'_>,
_infer_args: bool,
- _preceding_args: &[crate::GenericArg],
- ) -> crate::GenericArg {
+ _preceding_args: &[GenericArg<'db>],
+ ) -> GenericArg<'db> {
// Always create an inference var, even when `infer_args == false`. This helps with diagnostics,
// and I think it's also required in the presence of `impl Trait` (that must be inferred).
- match param_id {
- GenericParamId::TypeParamId(_) => self.ctx.table.new_type_var().cast(Interner),
- GenericParamId::ConstParamId(const_id) => self
- .ctx
- .table
- .new_const_var(self.ctx.db.const_param_ty(const_id))
- .cast(Interner),
- GenericParamId::LifetimeParamId(_) => {
- self.ctx.table.new_lifetime_var().cast(Interner)
- }
- }
+ self.ctx.table.next_var_for_param(param_id)
}
- fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg {
- match param_id {
- GenericParamId::TypeParamId(_) => self.ctx.table.new_type_var().cast(Interner),
- GenericParamId::ConstParamId(const_id) => self
- .ctx
- .table
- .new_const_var(self.ctx.db.const_param_ty(const_id))
- .cast(Interner),
- GenericParamId::LifetimeParamId(_) => {
- self.ctx.table.new_lifetime_var().cast(Interner)
- }
- }
+ fn parent_arg(&mut self, param_id: GenericParamId) -> GenericArg<'db> {
+ self.ctx.table.next_var_for_param(param_id)
}
fn report_elided_lifetimes_in_path(
@@ -2472,36 +2316,34 @@ impl<'db> InferenceContext<'db> {
)
}
- fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
- let callable_ty = self.table.structurally_resolve_type(callable_ty);
- if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
- let def: CallableDefId = from_chalk(self.db, *fn_def);
+ fn register_obligations_for_call(&mut self, callable_ty: Ty<'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(GenericDefId::from_callable(self.db, def));
- for predicate in generic_predicates.iter() {
- let (predicate, binders) = predicate
- .clone()
- .substitute(Interner, parameters)
- .into_value_and_skipped_binders();
- always!(binders.len(Interner) == 0); // quantified where clauses not yet handled
- self.push_obligation(predicate.cast(Interner));
+ self.db.generic_predicates_ns(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;
+ self.table.register_predicates(predicates.map(|predicate| {
+ Obligation::new(interner, ObligationCause::new(), param_env, predicate)
+ }));
}
// add obligation for trait implementation, if this is a trait method
- match def {
+ match fn_def.0 {
CallableDefId::FunctionId(f) => {
if let ItemContainerId::TraitId(trait_) = f.lookup(self.db).container {
// construct a TraitRef
let trait_params_len = generics(self.db, trait_.into()).len();
- let substs = Substitution::from_iter(
- Interner,
- // The generic parameters for the trait come after those for the
- // function.
- &parameters.as_slice(Interner)[..trait_params_len],
- );
- self.push_obligation(
- TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
- .cast(Interner),
+ let substs = GenericArgs::new_from_iter(
+ self.interner(),
+ parameters.as_slice()[..trait_params_len].iter().copied(),
);
+ self.table.register_predicate(Obligation::new(
+ self.interner(),
+ ObligationCause::new(),
+ self.table.trait_env.env,
+ TraitRef::new(self.interner(), trait_.into(), substs),
+ ));
}
}
CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
@@ -2510,11 +2352,10 @@ impl<'db> InferenceContext<'db> {
}
/// Returns the argument indices to skip.
- fn check_legacy_const_generics(&mut self, callee: Ty, args: &[ExprId]) -> Box<[u32]> {
- let (func, subst) = match callee.kind(Interner) {
- TyKind::FnDef(fn_id, subst) => {
- let callable = CallableDefId::from_chalk(self.db, *fn_id);
- let func = match callable {
+ fn check_legacy_const_generics(&mut self, callee: Ty<'db>, args: &[ExprId]) -> Box<[u32]> {
+ let (func, _subst) = match callee.kind() {
+ TyKind::FnDef(callable, subst) => {
+ let func = match callable.0 {
CallableDefId::FunctionId(f) => f,
_ => return Default::default(),
};
@@ -2542,15 +2383,10 @@ impl<'db> InferenceContext<'db> {
}
// check legacy const parameters
- for (subst_idx, arg_idx) in legacy_const_generics_indices.iter().copied().enumerate() {
- let arg = match subst.at(Interner, subst_idx).constant(Interner) {
- Some(c) => c,
- None => continue, // not a const parameter?
- };
+ for arg_idx in legacy_const_generics_indices.iter().copied() {
if arg_idx >= args.len() as u32 {
continue;
}
- let _ty = arg.data(Interner).ty.clone();
let expected = Expectation::none(); // FIXME use actual const ty, when that is lowered correctly
self.infer_expr(args[arg_idx as usize], &expected, ExprIsRead::Yes);
// FIXME: evaluate and unify with the const
@@ -2561,17 +2397,19 @@ impl<'db> InferenceContext<'db> {
}
/// Dereferences a single level of immutable referencing.
- fn deref_ty_if_possible(&mut self, ty: &Ty) -> Ty {
- let ty = self.table.structurally_resolve_type(ty);
- match ty.kind(Interner) {
- TyKind::Ref(Mutability::Not, _, inner) => self.table.structurally_resolve_type(inner),
+ fn deref_ty_if_possible(&mut self, ty: Ty<'db>) -> Ty<'db> {
+ let ty = self.table.try_structurally_resolve_type(ty);
+ match ty.kind() {
+ TyKind::Ref(_, inner, Mutability::Not) => {
+ self.table.try_structurally_resolve_type(inner)
+ }
_ => ty,
}
}
/// Enforces expectations on lhs type and rhs type depending on the operator and returns the
/// output type of the binary op.
- fn enforce_builtin_binop_types(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> Ty {
+ fn enforce_builtin_binop_types(&mut self, lhs: Ty<'db>, rhs: Ty<'db>, op: BinaryOp) -> Ty<'db> {
// Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work (See rust-lang/rust#57447).
let lhs = self.deref_ty_if_possible(lhs);
let rhs = self.deref_ty_if_possible(rhs);
@@ -2583,9 +2421,9 @@ impl<'db> InferenceContext<'db> {
let output_ty = match op {
BinaryOp::LogicOp(_) => {
- let bool_ = self.result.standard_types.bool_.clone();
- self.unify(&lhs, &bool_);
- self.unify(&rhs, &bool_);
+ let bool_ = self.types.bool;
+ self.unify(lhs, bool_);
+ self.unify(rhs, bool_);
bool_
}
@@ -2596,14 +2434,14 @@ impl<'db> InferenceContext<'db> {
BinaryOp::ArithOp(_) => {
// LHS, RHS, and result will have the same type
- self.unify(&lhs, &rhs);
+ self.unify(lhs, rhs);
lhs
}
BinaryOp::CmpOp(_) => {
// LHS and RHS will have the same type
- self.unify(&lhs, &rhs);
- self.result.standard_types.bool_.clone()
+ self.unify(lhs, rhs);
+ self.types.bool
}
BinaryOp::Assignment { op: None } => {
@@ -2614,10 +2452,10 @@ impl<'db> InferenceContext<'db> {
BinaryOp::Assignment { .. } => unreachable!("handled above"),
};
- if is_assign { self.result.standard_types.unit.clone() } else { output_ty }
+ if is_assign { self.types.unit } else { output_ty }
}
- fn is_builtin_binop(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> bool {
+ fn is_builtin_binop(&mut self, lhs: Ty<'db>, rhs: Ty<'db>, op: BinaryOp) -> bool {
// Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work (See rust-lang/rust#57447).
let lhs = self.deref_ty_if_possible(lhs);
let rhs = self.deref_ty_if_possible(rhs);
@@ -2644,27 +2482,25 @@ impl<'db> InferenceContext<'db> {
BinaryOp::ArithOp(ArithOp::BitAnd | ArithOp::BitOr | ArithOp::BitXor) => {
lhs.is_integral() && rhs.is_integral()
|| lhs.is_floating_point() && rhs.is_floating_point()
- || matches!(
- (lhs.kind(Interner), rhs.kind(Interner)),
- (TyKind::Scalar(Scalar::Bool), TyKind::Scalar(Scalar::Bool))
- )
+ || matches!((lhs.kind(), rhs.kind()), (TyKind::Bool, TyKind::Bool))
}
BinaryOp::CmpOp(_) => {
let is_scalar = |kind| {
matches!(
kind,
- &TyKind::Scalar(_)
+ TyKind::Bool
+ | TyKind::Char
+ | TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
| TyKind::FnDef(..)
- | TyKind::Function(_)
- | TyKind::Raw(..)
- | TyKind::InferenceVar(
- _,
- TyVariableKind::Integer | TyVariableKind::Float
- )
+ | TyKind::FnPtr(..)
+ | TyKind::RawPtr(..)
+ | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_))
)
};
- is_scalar(lhs.kind(Interner)) && is_scalar(rhs.kind(Interner))
+ is_scalar(lhs.kind()) && is_scalar(rhs.kind())
}
BinaryOp::Assignment { op: None } => {
@@ -2679,27 +2515,15 @@ impl<'db> InferenceContext<'db> {
pub(super) fn with_breakable_ctx<T>(
&mut self,
kind: BreakableKind,
- ty: Option<Ty>,
+ ty: Option<Ty<'db>>,
label: Option<LabelId>,
cb: impl FnOnce(&mut Self) -> T,
- ) -> (Option<Ty>, T) {
+ ) -> (Option<Ty<'db>>, T) {
self.breakables.push({
- BreakableContext {
- kind,
- may_break: false,
- coerce: ty.map(|ty| CoerceMany::new(ty.to_nextsolver(self.table.interner))),
- label,
- }
+ BreakableContext { kind, may_break: false, coerce: ty.map(CoerceMany::new), label }
});
let res = cb(self);
let ctx = self.breakables.pop().expect("breakable stack broken");
- (
- if ctx.may_break {
- ctx.coerce.map(|ctx| ctx.complete(self).to_chalk(self.table.interner))
- } else {
- None
- },
- res,
- )
+ (if ctx.may_break { ctx.coerce.map(|ctx| ctx.complete(self)) } else { None }, res)
}
}
diff --git a/crates/hir-ty/src/infer/fallback.rs b/crates/hir-ty/src/infer/fallback.rs
index 2022447ad4..b1c9146cc8 100644
--- a/crates/hir-ty/src/infer/fallback.rs
+++ b/crates/hir-ty/src/infer/fallback.rs
@@ -28,7 +28,7 @@ pub(crate) enum DivergingFallbackBehavior {
ToNever,
}
-impl<'db> InferenceContext<'db> {
+impl<'db> InferenceContext<'_, 'db> {
pub(super) fn type_inference_fallback(&mut self) {
debug!(
"type-inference-fallback start obligations: {:#?}",
@@ -324,7 +324,7 @@ impl<'db> InferenceContext<'db> {
FxHashMap::with_capacity_and_hasher(diverging_vids.len(), FxBuildHasher);
for &diverging_vid in &diverging_vids {
- let diverging_ty = Ty::new_var(self.table.interner, diverging_vid);
+ let diverging_ty = Ty::new_var(self.interner(), diverging_vid);
let root_vid = self.table.infer_ctxt.root_var(diverging_vid);
let can_reach_non_diverging = Dfs::new(&coercion_graph, root_vid.as_u32().into())
.iter(&coercion_graph)
diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs
index c798e9e050..9edbc9dda0 100644
--- a/crates/hir-ty/src/infer/mutability.rs
+++ b/crates/hir-ty/src/infer/mutability.rs
@@ -1,7 +1,6 @@
//! Finds if an expression is an immutable context or a mutable context, which is used in selecting
//! between `Deref` and `DerefMut` or `Index` and `IndexMut` or similar.
-use chalk_ir::{Mutability, cast::Cast};
use hir_def::{
hir::{
Array, AsmOperand, BinaryOp, BindingAnnotation, Expr, ExprId, Pat, PatId, Statement,
@@ -11,14 +10,19 @@ use hir_def::{
};
use hir_expand::name::Name;
use intern::sym;
+use rustc_ast_ir::Mutability;
+use rustc_type_ir::inherent::IntoKind;
+use crate::next_solver::infer::traits::{Obligation, ObligationCause};
+use crate::next_solver::{GenericArgs, TraitRef};
use crate::{
- Adjust, Adjustment, AutoBorrow, Interner, OverloadedDeref, TyBuilder, TyKind,
+ Adjust, Adjustment, AutoBorrow, OverloadedDeref,
infer::{Expectation, InferenceContext, expr::ExprIsRead},
- lower::lower_to_chalk_mutability,
+ lower_nextsolver::lower_mutability,
+ next_solver::TyKind,
};
-impl InferenceContext<'_> {
+impl<'db> InferenceContext<'_, 'db> {
pub(crate) fn infer_mut_body(&mut self) {
self.infer_mut_expr(self.body.body_expr, Mutability::Not);
}
@@ -141,8 +145,8 @@ impl InferenceContext<'_> {
target,
}) = base_adjustments
{
- if let TyKind::Ref(_, _, ty) = target.kind(Interner) {
- base_ty = Some(ty.clone());
+ if let TyKind::Ref(_, ty, _) = target.kind() {
+ base_ty = Some(ty);
}
*mutability = Mutability::Mut;
}
@@ -150,15 +154,24 @@ impl InferenceContext<'_> {
// Apply `IndexMut` obligation for non-assignee expr
if let Some(base_ty) = base_ty {
let index_ty = if let Some(ty) = self.result.type_of_expr.get(index) {
- ty.clone()
+ *ty
} else {
self.infer_expr(index, &Expectation::none(), ExprIsRead::Yes)
};
- let trait_ref = TyBuilder::trait_ref(self.db, index_trait)
- .push(base_ty)
- .fill(|_| index_ty.clone().cast(Interner))
- .build();
- self.push_obligation(trait_ref.cast(Interner));
+ let trait_ref = TraitRef::new(
+ self.interner(),
+ index_trait.into(),
+ GenericArgs::new_from_iter(
+ self.interner(),
+ [base_ty.into(), index_ty.into()],
+ ),
+ );
+ self.table.register_predicate(Obligation::new(
+ self.interner(),
+ ObligationCause::new(),
+ self.table.trait_env.env,
+ trait_ref,
+ ));
}
}
self.infer_mut_expr(base, mutability);
@@ -173,8 +186,8 @@ impl InferenceContext<'_> {
{
let ty = self.result.type_of_expr.get(*expr);
let is_mut_ptr = ty.is_some_and(|ty| {
- let ty = self.table.resolve_ty_shallow(ty);
- matches!(ty.kind(Interner), chalk_ir::TyKind::Raw(Mutability::Mut, _))
+ let ty = self.table.shallow_resolve(*ty);
+ matches!(ty.kind(), TyKind::RawPtr(_, Mutability::Mut))
});
if is_mut_ptr {
mutability = Mutability::Not;
@@ -200,7 +213,7 @@ impl InferenceContext<'_> {
self.infer_mut_expr(*expr, Mutability::Not);
}
Expr::Ref { expr, rawness: _, mutability } => {
- let mutability = lower_to_chalk_mutability(*mutability);
+ let mutability = lower_mutability(*mutability);
self.infer_mut_expr(*expr, mutability);
}
Expr::BinaryOp { lhs, rhs, op: Some(BinaryOp::Assignment { .. }) } => {
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 6e11fa942b..9f2f86dd3e 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -8,37 +8,35 @@ use hir_def::{
hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId},
};
use hir_expand::name::Name;
+use rustc_ast_ir::Mutability;
+use rustc_type_ir::inherent::{GenericArg as _, GenericArgs as _, IntoKind, SliceLike, Ty as _};
use stdx::TupleExt;
-use crate::infer::AllowTwoPhase;
-use crate::next_solver::mapping::{ChalkToNextSolver, NextSolverToChalk};
use crate::{
- DeclContext, DeclOrigin, InferenceDiagnostic, Interner, Mutability, Scalar, Substitution, Ty,
- TyBuilder, TyExt, TyKind,
- consteval::{self, try_const_usize, usize_const},
+ DeclContext, DeclOrigin, InferenceDiagnostic,
+ consteval_nextsolver::{self, try_const_usize, usize_const},
infer::{
- BindingMode, Expectation, InferenceContext, TypeMismatch, coerce::CoerceNever,
- expr::ExprIsRead,
+ AllowTwoPhase, BindingMode, Expectation, InferenceContext, TypeMismatch,
+ coerce::CoerceNever, expr::ExprIsRead,
},
- lower::lower_to_chalk_mutability,
- primitive::UintTy,
- static_lifetime,
+ lower_nextsolver::lower_mutability,
+ next_solver::{GenericArgs, Ty, TyKind},
};
-impl InferenceContext<'_> {
+impl<'db> InferenceContext<'_, 'db> {
/// Infers type for tuple struct pattern or its corresponding assignee expression.
///
/// Ellipses found in the original pattern or expression must be filtered out.
pub(super) fn infer_tuple_struct_pat_like(
&mut self,
path: Option<&Path>,
- expected: &Ty,
+ expected: Ty<'db>,
default_bm: BindingMode,
id: PatId,
ellipsis: Option<u32>,
subs: &[PatId],
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let (ty, def) = self.resolve_variant(id.into(), path, true);
let var_data = def.map(|it| it.fields(self.db));
if let Some(variant) = def {
@@ -56,12 +54,12 @@ impl InferenceContext<'_> {
}
}
- self.unify(&ty, expected);
+ self.unify(ty, expected);
match def {
_ if subs.is_empty() => {}
Some(def) => {
- let field_types = self.db.field_types(def);
+ let field_types = self.db.field_types_ns(def);
let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
@@ -85,10 +83,10 @@ impl InferenceContext<'_> {
{
// FIXME(DIAGNOSE): private tuple field
}
- let f = field_types[local_id].clone();
+ let f = field_types[local_id];
let expected_ty = match substs {
- Some(substs) => f.substitute(Interner, substs),
- None => f.substitute(Interner, &Substitution::empty(Interner)),
+ Some(substs) => f.instantiate(self.interner(), substs),
+ None => f.instantiate(self.interner(), &[]),
};
self.process_remote_user_written_ty(expected_ty)
}
@@ -96,13 +94,13 @@ impl InferenceContext<'_> {
}
};
- self.infer_pat(subpat, &expected_ty, default_bm, decl);
+ self.infer_pat(subpat, expected_ty, default_bm, decl);
}
}
None => {
let err_ty = self.err_ty();
for &inner in subs {
- self.infer_pat(inner, &err_ty, default_bm, decl);
+ self.infer_pat(inner, err_ty, default_bm, decl);
}
}
}
@@ -114,23 +112,23 @@ impl InferenceContext<'_> {
pub(super) fn infer_record_pat_like(
&mut self,
path: Option<&Path>,
- expected: &Ty,
+ expected: Ty<'db>,
default_bm: BindingMode,
id: PatId,
subs: impl ExactSizeIterator<Item = (Name, PatId)>,
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let (ty, def) = self.resolve_variant(id.into(), path, false);
if let Some(variant) = def {
self.write_variant_resolution(id.into(), variant);
}
- self.unify(&ty, expected);
+ self.unify(ty, expected);
match def {
_ if subs.len() == 0 => {}
Some(def) => {
- let field_types = self.db.field_types(def);
+ let field_types = self.db.field_types_ns(def);
let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
@@ -149,10 +147,10 @@ impl InferenceContext<'_> {
variant: def,
});
}
- let f = field_types[local_id].clone();
+ let f = field_types[local_id];
let expected_ty = match substs {
- Some(substs) => f.substitute(Interner, substs),
- None => f.substitute(Interner, &Substitution::empty(Interner)),
+ Some(substs) => f.instantiate(self.interner(), substs),
+ None => f.instantiate(self.interner(), &[]),
};
self.process_remote_user_written_ty(expected_ty)
}
@@ -167,13 +165,13 @@ impl InferenceContext<'_> {
}
};
- self.infer_pat(inner, &expected_ty, default_bm, decl);
+ self.infer_pat(inner, expected_ty, default_bm, decl);
}
}
None => {
let err_ty = self.err_ty();
for (_, inner) in subs {
- self.infer_pat(inner, &err_ty, default_bm, decl);
+ self.infer_pat(inner, err_ty, default_bm, decl);
}
}
}
@@ -186,16 +184,16 @@ impl InferenceContext<'_> {
/// Ellipses found in the original pattern or expression must be filtered out.
pub(super) fn infer_tuple_pat_like(
&mut self,
- expected: &Ty,
+ expected: Ty<'db>,
default_bm: BindingMode,
ellipsis: Option<u32>,
subs: &[PatId],
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let expected = self.table.structurally_resolve_type(expected);
- let expectations = match expected.as_tuple() {
- Some(parameters) => parameters.as_slice(Interner),
- _ => &[],
+ let expectations = match expected.kind() {
+ TyKind::Tuple(parameters) => parameters,
+ _ => self.types.empty_tys,
};
let ((pre, post), n_uncovered_patterns) = match ellipsis {
@@ -204,10 +202,8 @@ impl InferenceContext<'_> {
}
None => ((subs, &[][..]), 0),
};
- let mut expectations_iter = expectations
- .iter()
- .map(|a| a.assert_ty_ref(Interner).clone())
- .chain(repeat_with(|| self.table.new_type_var()));
+ let mut expectations_iter =
+ expectations.iter().chain(repeat_with(|| self.table.next_ty_var()));
let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + subs.len());
@@ -215,31 +211,35 @@ impl InferenceContext<'_> {
// Process pre
for (ty, pat) in inner_tys.iter_mut().zip(pre) {
- *ty = self.infer_pat(*pat, ty, default_bm, decl);
+ *ty = self.infer_pat(*pat, *ty, default_bm, decl);
}
// Process post
for (ty, pat) in inner_tys.iter_mut().skip(pre.len() + n_uncovered_patterns).zip(post) {
- *ty = self.infer_pat(*pat, ty, default_bm, decl);
+ *ty = self.infer_pat(*pat, *ty, default_bm, decl);
}
- TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
- .intern(Interner)
+ Ty::new_tup_from_iter(self.interner(), inner_tys.into_iter())
}
/// The resolver needs to be updated to the surrounding expression when inside assignment
/// (because there, `Pat::Path` can refer to a variable).
- pub(super) fn infer_top_pat(&mut self, pat: PatId, expected: &Ty, decl: Option<DeclContext>) {
+ pub(super) fn infer_top_pat(
+ &mut self,
+ pat: PatId,
+ expected: Ty<'db>,
+ decl: Option<DeclContext>,
+ ) {
self.infer_pat(pat, expected, BindingMode::default(), decl);
}
fn infer_pat(
&mut self,
pat: PatId,
- expected: &Ty,
+ expected: Ty<'db>,
mut default_bm: BindingMode,
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let mut expected = self.table.structurally_resolve_type(expected);
if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment {
@@ -251,9 +251,9 @@ impl InferenceContext<'_> {
default_bm = BindingMode::Move;
} else if self.is_non_ref_pat(self.body, pat) {
let mut pat_adjustments = Vec::new();
- while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
- pat_adjustments.push(expected.clone());
- expected = self.table.structurally_resolve_type(inner);
+ while let TyKind::Ref(_lifetime, inner, mutability) = expected.kind() {
+ pat_adjustments.push(expected);
+ expected = self.table.try_structurally_resolve_type(inner);
default_bm = match default_bm {
BindingMode::Move => BindingMode::Ref(mutability),
BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
@@ -273,25 +273,21 @@ impl InferenceContext<'_> {
let ty = match &self.body[pat] {
Pat::Tuple { args, ellipsis } => {
- self.infer_tuple_pat_like(&expected, default_bm, *ellipsis, args, decl)
+ self.infer_tuple_pat_like(expected, default_bm, *ellipsis, args, decl)
}
Pat::Or(pats) => {
for pat in pats.iter() {
- self.infer_pat(*pat, &expected, default_bm, decl);
+ self.infer_pat(*pat, expected, default_bm, decl);
}
- expected.clone()
+ expected
+ }
+ &Pat::Ref { pat, mutability } => {
+ self.infer_ref_pat(pat, lower_mutability(mutability), expected, default_bm, decl)
}
- &Pat::Ref { pat, mutability } => self.infer_ref_pat(
- pat,
- lower_to_chalk_mutability(mutability),
- &expected,
- default_bm,
- decl,
- ),
Pat::TupleStruct { path: p, args: subpats, ellipsis } => self
.infer_tuple_struct_pat_like(
p.as_deref(),
- &expected,
+ expected,
default_bm,
pat,
*ellipsis,
@@ -300,29 +296,26 @@ impl InferenceContext<'_> {
),
Pat::Record { path: p, args: fields, ellipsis: _ } => {
let subs = fields.iter().map(|f| (f.name.clone(), f.pat));
- self.infer_record_pat_like(p.as_deref(), &expected, default_bm, pat, subs, decl)
+ self.infer_record_pat_like(p.as_deref(), expected, default_bm, pat, subs, decl)
}
Pat::Path(path) => {
let ty = self.infer_path(path, pat.into()).unwrap_or_else(|| self.err_ty());
- let ty_inserted_vars = self.insert_type_vars_shallow(ty.clone());
+ let ty_inserted_vars = self.insert_type_vars_shallow(ty);
match self.coerce(
pat.into(),
- expected.to_nextsolver(self.table.interner),
- ty_inserted_vars.to_nextsolver(self.table.interner),
+ expected,
+ ty_inserted_vars,
AllowTwoPhase::No,
CoerceNever::Yes,
) {
Ok(coerced_ty) => {
- self.write_pat_ty(pat, coerced_ty.to_chalk(self.table.interner));
+ self.write_pat_ty(pat, coerced_ty);
return self.pat_ty_after_adjustment(pat);
}
Err(_) => {
self.result.type_mismatches.insert(
pat.into(),
- TypeMismatch {
- expected: expected.clone(),
- actual: ty_inserted_vars.clone(),
- },
+ TypeMismatch { expected, actual: ty_inserted_vars },
);
self.write_pat_ty(pat, ty);
// We return `expected` to prevent cascading errors. I guess an alternative is to
@@ -332,81 +325,77 @@ impl InferenceContext<'_> {
}
}
Pat::Bind { id, subpat } => {
- return self.infer_bind_pat(pat, *id, default_bm, *subpat, &expected, decl);
+ return self.infer_bind_pat(pat, *id, default_bm, *subpat, expected, decl);
}
Pat::Slice { prefix, slice, suffix } => {
- self.infer_slice_pat(&expected, prefix, slice, suffix, default_bm, decl)
+ self.infer_slice_pat(expected, prefix, *slice, suffix, default_bm, decl)
}
- Pat::Wild => expected.clone(),
+ Pat::Wild => expected,
Pat::Range { .. } => {
// FIXME: do some checks here.
- expected.clone()
+ expected
}
&Pat::Lit(expr) => {
// Don't emit type mismatches again, the expression lowering already did that.
- let ty = self.infer_lit_pat(expr, &expected);
+ let ty = self.infer_lit_pat(expr, expected);
self.write_pat_ty(pat, ty);
return self.pat_ty_after_adjustment(pat);
}
Pat::Box { inner } => match self.resolve_boxed_box() {
Some(box_adt) => {
let (inner_ty, alloc_ty) = match expected.as_adt() {
- Some((adt, subst)) if adt == box_adt => (
- subst.at(Interner, 0).assert_ty_ref(Interner).clone(),
- subst.as_slice(Interner).get(1).and_then(|a| a.ty(Interner).cloned()),
- ),
- _ => (self.result.standard_types.unknown.clone(), None),
+ Some((adt, subst)) if adt == box_adt => {
+ (subst.type_at(0), subst.as_slice().get(1).and_then(|a| a.as_type()))
+ }
+ _ => (self.types.error, None),
};
- let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm, decl);
- let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty);
-
- if let Some(alloc_ty) = alloc_ty {
- b = b.push(alloc_ty);
- }
- b.fill_with_defaults(self.db, || self.table.new_type_var()).build()
+ let inner_ty = self.infer_pat(*inner, inner_ty, default_bm, decl);
+ Ty::new_adt(
+ self.interner(),
+ box_adt,
+ GenericArgs::fill_with_defaults(
+ self.interner(),
+ box_adt.into(),
+ std::iter::once(inner_ty.into()).chain(alloc_ty.map(Into::into)),
+ |_, _, id, _| self.table.next_var_for_param(id),
+ ),
+ )
}
None => self.err_ty(),
},
Pat::ConstBlock(expr) => {
let old_inside_assign = std::mem::replace(&mut self.inside_assignment, false);
- let result = self.infer_expr(
- *expr,
- &Expectation::has_type(expected.clone()),
- ExprIsRead::Yes,
- );
+ let result =
+ self.infer_expr(*expr, &Expectation::has_type(expected), ExprIsRead::Yes);
self.inside_assignment = old_inside_assign;
result
}
Pat::Expr(expr) => {
let old_inside_assign = std::mem::replace(&mut self.inside_assignment, false);
// LHS of assignment doesn't constitute reads.
- let result = self.infer_expr_coerce(
- *expr,
- &Expectation::has_type(expected.clone()),
- ExprIsRead::No,
- );
+ let result =
+ self.infer_expr_coerce(*expr, &Expectation::has_type(expected), ExprIsRead::No);
// We are returning early to avoid the unifiability check below.
let lhs_ty = self.insert_type_vars_shallow(result);
let ty = match self.coerce(
pat.into(),
- expected.to_nextsolver(self.table.interner),
- lhs_ty.to_nextsolver(self.table.interner),
+ expected,
+ lhs_ty,
AllowTwoPhase::No,
CoerceNever::Yes,
) {
- Ok(ty) => ty.to_chalk(self.table.interner),
+ Ok(ty) => ty,
Err(_) => {
- self.result.type_mismatches.insert(
- pat.into(),
- TypeMismatch { expected: expected.clone(), actual: lhs_ty.clone() },
- );
+ self.result
+ .type_mismatches
+ .insert(pat.into(), TypeMismatch { expected, actual: lhs_ty });
// `rhs_ty` is returned so no further type mismatches are
// reported because of this mismatch.
expected
}
};
- self.write_pat_ty(pat, ty.clone());
+ self.write_pat_ty(pat, ty);
self.inside_assignment = old_inside_assign;
return ty;
}
@@ -415,46 +404,43 @@ impl InferenceContext<'_> {
// use a new type variable if we got error type here
let ty = self.insert_type_vars_shallow(ty);
// FIXME: This never check is odd, but required with out we do inference right now
- if !expected.is_never() && !self.unify(&ty, &expected) {
- self.result
- .type_mismatches
- .insert(pat.into(), TypeMismatch { expected, actual: ty.clone() });
+ if !expected.is_never() && !self.unify(ty, expected) {
+ self.result.type_mismatches.insert(pat.into(), TypeMismatch { expected, actual: ty });
}
self.write_pat_ty(pat, ty);
self.pat_ty_after_adjustment(pat)
}
- fn pat_ty_after_adjustment(&self, pat: PatId) -> Ty {
- self.result
+ fn pat_ty_after_adjustment(&self, pat: PatId) -> Ty<'db> {
+ *self
+ .result
.pat_adjustments
.get(&pat)
.and_then(|it| it.first())
.unwrap_or(&self.result.type_of_pat[pat])
- .clone()
}
fn infer_ref_pat(
&mut self,
inner_pat: PatId,
mutability: Mutability,
- expected: &Ty,
+ expected: Ty<'db>,
default_bm: BindingMode,
decl: Option<DeclContext>,
- ) -> Ty {
- let (expectation_type, expectation_lt) = match expected.as_reference() {
- Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime),
- None => {
- let inner_ty = self.table.new_type_var();
- let inner_lt = self.table.new_lifetime_var();
- let ref_ty =
- TyKind::Ref(mutability, inner_lt.clone(), inner_ty.clone()).intern(Interner);
+ ) -> Ty<'db> {
+ let (expectation_type, expectation_lt) = match expected.kind() {
+ TyKind::Ref(lifetime, inner_ty, _exp_mut) => (inner_ty, lifetime),
+ _ => {
+ let inner_ty = self.table.next_ty_var();
+ let inner_lt = self.table.next_region_var();
+ let ref_ty = Ty::new_ref(self.interner(), inner_lt, inner_ty, mutability);
// Unification failure will be reported by the caller.
- self.unify(&ref_ty, expected);
+ self.unify(ref_ty, expected);
(inner_ty, inner_lt)
}
};
- let subty = self.infer_pat(inner_pat, &expectation_type, default_bm, decl);
- TyKind::Ref(mutability, expectation_lt, subty).intern(Interner)
+ let subty = self.infer_pat(inner_pat, expectation_type, default_bm, decl);
+ Ty::new_ref(self.interner(), expectation_lt, subty, mutability)
}
fn infer_bind_pat(
@@ -463,9 +449,9 @@ impl InferenceContext<'_> {
binding: BindingId,
default_bm: BindingMode,
subpat: Option<PatId>,
- expected: &Ty,
+ expected: Ty<'db>,
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let Binding { mode, .. } = self.body[binding];
let mode = if mode == BindingAnnotation::Unannotated {
default_bm
@@ -476,31 +462,31 @@ impl InferenceContext<'_> {
let inner_ty = match subpat {
Some(subpat) => self.infer_pat(subpat, expected, default_bm, decl),
- None => expected.clone(),
+ None => expected,
};
let inner_ty = self.insert_type_vars_shallow(inner_ty);
let bound_ty = match mode {
BindingMode::Ref(mutability) => {
- let inner_lt = self.table.new_lifetime_var();
- TyKind::Ref(mutability, inner_lt, inner_ty.clone()).intern(Interner)
+ let inner_lt = self.table.next_region_var();
+ Ty::new_ref(self.interner(), inner_lt, inner_ty, mutability)
}
- BindingMode::Move => inner_ty.clone(),
+ BindingMode::Move => inner_ty,
};
- self.write_pat_ty(pat, inner_ty.clone());
+ self.write_pat_ty(pat, inner_ty);
self.write_binding_ty(binding, bound_ty);
inner_ty
}
fn infer_slice_pat(
&mut self,
- expected: &Ty,
+ expected: Ty<'db>,
prefix: &[PatId],
- slice: &Option<PatId>,
+ slice: Option<PatId>,
suffix: &[PatId],
default_bm: BindingMode,
decl: Option<DeclContext>,
- ) -> Ty {
+ ) -> Ty<'db> {
let expected = self.table.structurally_resolve_type(expected);
// If `expected` is an infer ty, we try to equate it to an array if the given pattern
@@ -510,56 +496,61 @@ impl InferenceContext<'_> {
&& let Some(resolved_array_ty) =
self.try_resolve_slice_ty_to_array_ty(prefix, suffix, slice)
{
- self.unify(&expected, &resolved_array_ty);
+ self.unify(expected, resolved_array_ty);
}
- let expected = self.table.structurally_resolve_type(&expected);
- let elem_ty = match expected.kind(Interner) {
- TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
+ let expected = self.table.try_structurally_resolve_type(expected);
+ let elem_ty = match expected.kind() {
+ TyKind::Array(st, _) | TyKind::Slice(st) => st,
_ => self.err_ty(),
};
for &pat_id in prefix.iter().chain(suffix.iter()) {
- self.infer_pat(pat_id, &elem_ty, default_bm, decl);
+ self.infer_pat(pat_id, elem_ty, default_bm, decl);
}
- if let &Some(slice_pat_id) = slice {
- let rest_pat_ty = match expected.kind(Interner) {
+ if let Some(slice_pat_id) = slice {
+ let rest_pat_ty = match expected.kind() {
TyKind::Array(_, length) => {
let len = try_const_usize(self.db, length);
let len =
len.and_then(|len| len.checked_sub((prefix.len() + suffix.len()) as u128));
- TyKind::Array(elem_ty.clone(), usize_const(self.db, len, self.resolver.krate()))
+ Ty::new_array_with_const_len(
+ self.interner(),
+ elem_ty,
+ usize_const(self.db, len, self.resolver.krate()),
+ )
}
- _ => TyKind::Slice(elem_ty.clone()),
- }
- .intern(Interner);
- self.infer_pat(slice_pat_id, &rest_pat_ty, default_bm, decl);
+ _ => Ty::new_slice(self.interner(), elem_ty),
+ };
+ self.infer_pat(slice_pat_id, rest_pat_ty, default_bm, decl);
}
- match expected.kind(Interner) {
- TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
- _ => TyKind::Slice(elem_ty),
+ match expected.kind() {
+ TyKind::Array(_, const_) => {
+ Ty::new_array_with_const_len(self.interner(), elem_ty, const_)
+ }
+ _ => Ty::new_slice(self.interner(), elem_ty),
}
- .intern(Interner)
}
- fn infer_lit_pat(&mut self, expr: ExprId, expected: &Ty) -> Ty {
+ fn infer_lit_pat(&mut self, expr: ExprId, expected: Ty<'db>) -> Ty<'db> {
// Like slice patterns, byte string patterns can denote both `&[u8; N]` and `&[u8]`.
if let Expr::Literal(Literal::ByteString(_)) = self.body[expr]
- && let Some((inner, ..)) = expected.as_reference()
+ && let TyKind::Ref(_, inner, _) = expected.kind()
{
- let inner = self.table.structurally_resolve_type(inner);
- if matches!(inner.kind(Interner), TyKind::Slice(_)) {
- let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
- let slice_ty = TyKind::Slice(elem_ty).intern(Interner);
- let ty = TyKind::Ref(Mutability::Not, static_lifetime(), slice_ty).intern(Interner);
- self.write_expr_ty(expr, ty.clone());
+ let inner = self.table.try_structurally_resolve_type(inner);
+ if matches!(inner.kind(), TyKind::Slice(_)) {
+ let elem_ty = self.types.u8;
+ let slice_ty = Ty::new_slice(self.interner(), elem_ty);
+ let ty =
+ Ty::new_ref(self.interner(), self.types.re_static, slice_ty, Mutability::Not);
+ self.write_expr_ty(expr, ty);
return ty;
}
}
- self.infer_expr(expr, &Expectation::has_type(expected.clone()), ExprIsRead::Yes)
+ self.infer_expr(expr, &Expectation::has_type(expected), ExprIsRead::Yes)
}
fn is_non_ref_pat(&mut self, body: &hir_def::expr_store::Body, pat: PatId) -> bool {
@@ -593,17 +584,21 @@ impl InferenceContext<'_> {
&mut self,
before: &[PatId],
suffix: &[PatId],
- slice: &Option<PatId>,
- ) -> Option<Ty> {
- if !slice.is_none() {
+ slice: Option<PatId>,
+ ) -> Option<Ty<'db>> {
+ if slice.is_some() {
return None;
}
let len = before.len() + suffix.len();
- let size = consteval::usize_const(self.db, Some(len as u128), self.owner.krate(self.db));
-
- let elem_ty = self.table.new_type_var();
- let array_ty = TyKind::Array(elem_ty, size).intern(Interner);
+ let size = consteval_nextsolver::usize_const(
+ self.db,
+ Some(len as u128),
+ self.owner.krate(self.db),
+ );
+
+ let elem_ty = self.table.next_ty_var();
+ let array_ty = Ty::new_array_with_const_len(self.interner(), elem_ty, size);
Some(array_ty)
}
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 733f3c2788..7517272362 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -1,52 +1,50 @@
//! Path expression resolution.
-use chalk_ir::cast::Cast;
use hir_def::{
- AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup,
+ AdtId, AssocItemId, GenericDefId, GenericParamId, ItemContainerId, Lookup,
expr_store::path::{Path, PathSegment},
resolver::{ResolveValueResult, TypeNs, ValueNs},
};
use hir_expand::name::Name;
+use rustc_type_ir::inherent::{SliceLike, Ty as _};
use stdx::never;
use crate::{
- InferenceDiagnostic, Interner, LifetimeElisionKind, Substitution, TraitRef, TraitRefExt, Ty,
- TyBuilder, TyExt, TyKind, ValueTyDefId,
- builder::ParamKind,
- consteval, error_lifetime,
+ InferenceDiagnostic, ValueTyDefId, consteval_nextsolver,
generics::generics,
infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext,
+ lower_nextsolver::LifetimeElisionKind,
method_resolution::{self, VisibleFromModule},
next_solver::{
- DbInterner,
- mapping::{ChalkToNextSolver, NextSolverToChalk},
+ GenericArg, GenericArgs, TraitRef, Ty,
+ infer::traits::{Obligation, ObligationCause},
},
- to_chalk_trait_id,
};
use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource};
-impl<'db> InferenceContext<'db> {
- pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty> {
+impl<'db> InferenceContext<'_, 'db> {
+ pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty<'db>> {
let (value_def, generic_def, substs) = match self.resolve_value_path(path, id)? {
ValuePathResolution::GenericDef(value_def, generic_def, substs) => {
(value_def, generic_def, substs)
}
ValuePathResolution::NonGeneric(ty) => return Some(ty),
};
- let substs =
- self.process_remote_user_written_ty::<_, crate::next_solver::GenericArgs<'db>>(substs);
+ let args = self.process_remote_user_written_ty(substs);
- self.add_required_obligations_for_value_path(generic_def, &substs);
+ self.add_required_obligations_for_value_path(generic_def, args);
- let interner = DbInterner::new_with(self.db, None, None);
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- let ty = self.db.value_ty(value_def)?.instantiate(interner, args).to_chalk(interner);
+ let ty = self.db.value_ty(value_def)?.instantiate(self.interner(), args);
let ty = self.process_remote_user_written_ty(ty);
Some(ty)
}
- fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<ValuePathResolution> {
+ fn resolve_value_path(
+ &mut self,
+ path: &Path,
+ id: ExprOrPatId,
+ ) -> Option<ValuePathResolution<'db>> {
let (value, self_subst) = self.resolve_value_path_inner(path, id, false)?;
let value_def: ValueTyDefId = match value {
@@ -65,7 +63,7 @@ impl<'db> InferenceContext<'db> {
}
ValueNs::LocalBinding(pat) => {
return match self.result.type_of_binding.get(pat) {
- Some(ty) => Some(ValuePathResolution::NonGeneric(ty.clone())),
+ Some(ty) => Some(ValuePathResolution::NonGeneric(*ty)),
None => {
never!("uninferred pattern?");
None
@@ -73,17 +71,12 @@ impl<'db> InferenceContext<'db> {
};
}
ValueNs::ImplSelf(impl_id) => {
- let generics = crate::generics::generics(self.db, impl_id.into());
- let interner = DbInterner::new_with(self.db, None, None);
- let substs = generics.placeholder_subst(self.db);
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- let ty =
- self.db.impl_self_ty(impl_id).instantiate(interner, args).to_chalk(interner);
+ let ty = self.db.impl_self_ty(impl_id).instantiate_identity();
return if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
Some(ValuePathResolution::GenericDef(
struct_id.into(),
struct_id.into(),
- substs.clone(),
+ substs,
))
} else {
// FIXME: report error, invalid Self reference
@@ -91,15 +84,14 @@ impl<'db> InferenceContext<'db> {
};
}
ValueNs::GenericParam(it) => {
- return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty(it)));
+ return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty_ns(it)));
}
};
let generic_def = value_def.to_generic_def_id(self.db);
if let GenericDefId::StaticId(_) = generic_def {
- let interner = DbInterner::new_with(self.db, None, None);
// `Static` is the kind of item that can never be generic currently. We can just skip the binders to get its type.
- let ty = self.db.value_ty(value_def)?.skip_binder().to_chalk(interner);
+ let ty = self.db.value_ty(value_def)?.skip_binder();
return Some(ValuePathResolution::NonGeneric(ty));
};
@@ -111,57 +103,34 @@ impl<'db> InferenceContext<'db> {
}
path_ctx.substs_from_path(value_def, true, false)
});
- let substs = substs.as_slice(Interner);
-
- if let ValueNs::EnumVariantId(_) = value {
- let mut it = substs
- .iter()
- .chain(self_subst.as_ref().map_or(&[][..], |s| s.as_slice(Interner)))
- .cloned();
- let builder = TyBuilder::subst_for_def(self.db, generic_def, None);
- let substs = builder
- .fill(|x| {
- it.next().unwrap_or_else(|| match x {
- ParamKind::Type => {
- self.result.standard_types.unknown.clone().cast(Interner)
- }
- ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
- ParamKind::Lifetime => error_lifetime().cast(Interner),
- })
- })
- .build();
- return Some(ValuePathResolution::GenericDef(value_def, generic_def, substs));
- }
-
- let parent_substs = self_subst.or_else(|| {
- let generics = generics(self.db, generic_def);
- let parent_params_len = generics.parent_generics()?.len();
- let parent_args = &substs[..parent_params_len];
- Some(Substitution::from_iter(Interner, parent_args))
- });
- let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner));
- let mut it = substs.iter().skip(parent_substs_len).cloned();
- let builder = TyBuilder::subst_for_def(self.db, generic_def, parent_substs);
- let substs = builder
- .fill(|x| {
- it.next().unwrap_or_else(|| match x {
- ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner),
- ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
- ParamKind::Lifetime => error_lifetime().cast(Interner),
- })
- })
- .build();
+ let parent_substs_len = self_subst.map_or(0, |it| it.len());
+ let substs = GenericArgs::fill_rest(
+ self.interner(),
+ generic_def.into(),
+ self_subst.iter().flat_map(|it| it.iter()).chain(substs.iter().skip(parent_substs_len)),
+ |_, _, id, _| self.error_param(id),
+ );
Some(ValuePathResolution::GenericDef(value_def, generic_def, substs))
}
+ fn error_param(&mut self, id: GenericParamId) -> GenericArg<'db> {
+ match id {
+ GenericParamId::TypeParamId(_) => self.types.error.into(),
+ GenericParamId::ConstParamId(id) => {
+ consteval_nextsolver::unknown_const_as_generic(self.db.const_param_ty_ns(id))
+ }
+ GenericParamId::LifetimeParamId(_) => self.types.re_error.into(),
+ }
+ }
+
pub(super) fn resolve_value_path_inner(
&mut self,
path: &Path,
id: ExprOrPatId,
no_diagnostics: bool,
- ) -> Option<(ValueNs, Option<chalk_ir::Substitution<Interner>>)> {
+ ) -> Option<(ValueNs, Option<GenericArgs<'db>>)> {
// Don't use `self.make_ty()` here as we need `orig_ns`.
let mut ctx = TyLoweringContext::new(
self.db,
@@ -211,7 +180,7 @@ impl<'db> InferenceContext<'db> {
let (resolution, substs) = match (def, is_before_last) {
(TypeNs::TraitId(trait_), true) => {
- let self_ty = self.table.new_type_var();
+ let self_ty = self.table.next_ty_var();
let trait_ref =
path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty, true);
drop_ctx(ctx, no_diagnostics);
@@ -225,7 +194,7 @@ impl<'db> InferenceContext<'db> {
path_ctx.ignore_last_segment();
let (ty, _) = path_ctx.lower_partly_resolved_path(def, true);
drop_ctx(ctx, no_diagnostics);
- if ty.is_unknown() {
+ if ty.is_ty_error() {
return None;
}
@@ -241,21 +210,25 @@ impl<'db> InferenceContext<'db> {
return Some((value, self_subst));
#[inline]
- fn drop_ctx(mut ctx: TyLoweringContext<'_>, no_diagnostics: bool) {
+ fn drop_ctx(mut ctx: TyLoweringContext<'_, '_>, no_diagnostics: bool) {
if no_diagnostics {
ctx.forget_diagnostics();
}
}
}
- fn add_required_obligations_for_value_path(&mut self, def: GenericDefId, subst: &Substitution) {
- let predicates = self.db.generic_predicates(def);
- for predicate in predicates.iter() {
- let (predicate, binders) =
- predicate.clone().substitute(Interner, &subst).into_value_and_skipped_binders();
- // Quantified where clauses are not yet handled.
- stdx::always!(binders.is_empty(Interner));
- self.push_obligation(predicate.cast(Interner));
+ fn add_required_obligations_for_value_path(
+ &mut self,
+ def: GenericDefId,
+ subst: GenericArgs<'db>,
+ ) {
+ let predicates = self.db.generic_predicates_ns(def);
+ let interner = self.interner();
+ let param_env = self.table.trait_env.env;
+ if let Some(predicates) = predicates.instantiate(self.interner(), subst) {
+ self.table.register_predicates(predicates.map(|predicate| {
+ Obligation::new(interner, ObligationCause::new(), param_env, predicate)
+ }));
}
// We need to add `Self: Trait` obligation when `def` is a trait assoc item.
@@ -267,21 +240,27 @@ impl<'db> InferenceContext<'db> {
if let ItemContainerId::TraitId(trait_) = container {
let parent_len = generics(self.db, def).parent_generics().map_or(0, |g| g.len_self());
- let parent_subst =
- Substitution::from_iter(Interner, subst.iter(Interner).take(parent_len));
- let trait_ref =
- TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: parent_subst };
- self.push_obligation(trait_ref.cast(Interner));
+ let parent_subst = GenericArgs::new_from_iter(
+ interner,
+ subst.as_slice()[..parent_len].iter().copied(),
+ );
+ let trait_ref = TraitRef::new(interner, trait_.into(), parent_subst);
+ self.table.register_predicate(Obligation::new(
+ interner,
+ ObligationCause::new(),
+ param_env,
+ trait_ref,
+ ));
}
}
fn resolve_trait_assoc_item(
&mut self,
- trait_ref: TraitRef,
+ trait_ref: TraitRef<'db>,
segment: PathSegment<'_>,
id: ExprOrPatId,
- ) -> Option<(ValueNs, Substitution)> {
- let trait_ = trait_ref.hir_trait_id();
+ ) -> Option<(ValueNs, GenericArgs<'db>)> {
+ let trait_ = trait_ref.def_id.0;
let item =
trait_.trait_items(self.db).items.iter().map(|(_name, id)| *id).find_map(|item| {
match item {
@@ -309,25 +288,25 @@ impl<'db> InferenceContext<'db> {
AssocItemId::TypeAliasId(_) => unreachable!(),
};
- self.write_assoc_resolution(id, item, trait_ref.substitution.clone());
- Some((def, trait_ref.substitution))
+ self.write_assoc_resolution(id, item, trait_ref.args);
+ Some((def, trait_ref.args))
}
fn resolve_ty_assoc_item(
&mut self,
- ty: Ty,
+ ty: Ty<'db>,
name: &Name,
id: ExprOrPatId,
- ) -> Option<(ValueNs, Substitution)> {
- if let TyKind::Error = ty.kind(Interner) {
+ ) -> Option<(ValueNs, GenericArgs<'db>)> {
+ if ty.is_ty_error() {
return None;
}
- if let Some(result) = self.resolve_enum_variant_on_ty(&ty, name, id) {
+ if let Some(result) = self.resolve_enum_variant_on_ty(ty, name, id) {
return Some(result);
}
- let canonical_ty = self.canonicalize(ty.clone().to_nextsolver(self.table.interner));
+ let canonical_ty = self.canonicalize(ty);
let mut not_visible = None;
let res = method_resolution::iterate_method_candidates(
@@ -362,24 +341,28 @@ impl<'db> InferenceContext<'db> {
};
let substs = match container {
ItemContainerId::ImplId(impl_id) => {
- let interner = DbInterner::new_with(self.db, None, None);
- let impl_substs = TyBuilder::subst_for_def(self.db, impl_id, None)
- .fill_with_inference_vars(&mut self.table)
- .build();
- let args: crate::next_solver::GenericArgs<'_> = impl_substs.to_nextsolver(interner);
+ let impl_substs = self.table.fresh_args_for_item(impl_id.into());
let impl_self_ty =
- self.db.impl_self_ty(impl_id).instantiate(interner, args).to_chalk(interner);
- self.unify(&impl_self_ty, &ty);
+ self.db.impl_self_ty(impl_id).instantiate(self.interner(), impl_substs);
+ self.unify(impl_self_ty, ty);
impl_substs
}
ItemContainerId::TraitId(trait_) => {
// we're picking this method
- let trait_ref = TyBuilder::trait_ref(self.db, trait_)
- .push(ty.clone())
- .fill_with_inference_vars(&mut self.table)
- .build();
- self.push_obligation(trait_ref.clone().cast(Interner));
- trait_ref.substitution
+ let args = GenericArgs::fill_rest(
+ self.interner(),
+ trait_.into(),
+ [ty.into()],
+ |_, _, id, _| self.table.next_var_for_param(id),
+ );
+ let trait_ref = TraitRef::new(self.interner(), trait_.into(), args);
+ self.table.register_predicate(Obligation::new(
+ self.interner(),
+ ObligationCause::new(),
+ self.table.trait_env.env,
+ trait_ref,
+ ));
+ args
}
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
never!("assoc item contained in module/extern block");
@@ -387,7 +370,7 @@ impl<'db> InferenceContext<'db> {
}
};
- self.write_assoc_resolution(id, item, substs.clone());
+ self.write_assoc_resolution(id, item, substs);
if !visible {
self.push_diagnostic(InferenceDiagnostic::PrivateAssocItem { id, item });
}
@@ -396,11 +379,11 @@ impl<'db> InferenceContext<'db> {
fn resolve_enum_variant_on_ty(
&mut self,
- ty: &Ty,
+ ty: Ty<'db>,
name: &Name,
id: ExprOrPatId,
- ) -> Option<(ValueNs, Substitution)> {
- let ty = self.table.structurally_resolve_type(ty);
+ ) -> Option<(ValueNs, GenericArgs<'db>)> {
+ let ty = self.table.try_structurally_resolve_type(ty);
let (enum_id, subst) = match ty.as_adt() {
Some((AdtId::EnumId(e), subst)) => (e, subst),
_ => return None,
@@ -408,14 +391,14 @@ impl<'db> InferenceContext<'db> {
let enum_data = enum_id.enum_variants(self.db);
let variant = enum_data.variant(name)?;
self.write_variant_resolution(id, variant.into());
- Some((ValueNs::EnumVariantId(variant), subst.clone()))
+ Some((ValueNs::EnumVariantId(variant), subst))
}
}
#[derive(Debug)]
-enum ValuePathResolution {
+enum ValuePathResolution<'db> {
// It's awkward to wrap a single ID in two enums, but we need both and this saves fallible
// conversion between them + `unwrap()`.
- GenericDef(ValueTyDefId, GenericDefId, Substitution),
- NonGeneric(Ty),
+ GenericDef(ValueTyDefId, GenericDefId, GenericArgs<'db>),
+ NonGeneric(Ty<'db>),
}
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 108cf5b1a2..89bab4e59c 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -2,49 +2,46 @@
use std::fmt;
-use chalk_ir::{
- CanonicalVarKind, TyVariableKind, cast::Cast, fold::TypeFoldable, interner::HasInterner,
-};
-use either::Either;
+use chalk_ir::cast::Cast;
+use hir_def::GenericParamId;
use hir_def::{AdtId, lang_item::LangItem};
use hir_expand::name::Name;
use intern::sym;
use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_type_ir::{DebruijnIndex, InferConst, InferTy, RegionVid};
use rustc_type_ir::{
- TyVid, TypeVisitableExt, UpcastFrom,
- inherent::{IntoKind, Span, Term as _, Ty as _},
- relate::{Relate, solver_relating::RelateExt},
+ TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UpcastFrom,
+ inherent::{Const as _, IntoKind, Ty as _},
solve::{Certainty, GoalSource},
};
use smallvec::SmallVec;
use triomphe::Arc;
-use super::{InferResult, InferenceContext, TypeError};
+use crate::next_solver::{Binder, ConstKind, GenericArgs, RegionKind, SolverDefId};
use crate::{
- AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, GenericArg, GenericArgData,
- InferenceVar, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution, TraitEnvironment, Ty,
- TyExt, TyKind, VariableKind,
- consteval::unknown_const,
- db::HirDatabase,
- fold_generic_args, fold_tys_and_consts,
+ Interner, TraitEnvironment,
+ db::{HirDatabase, InternedOpaqueTyId},
+ infer::InferenceContext,
next_solver::{
- self, ClauseKind, DbInterner, ErrorGuaranteed, Predicate, PredicateKind, SolverDefIds,
- Term, TraitRef,
- fulfill::FulfillmentCtxt,
+ self, AliasTy, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg, Predicate,
+ PredicateKind, Region, SolverDefIds, TraitRef, Ty, TyKind, TypingMode,
+ fulfill::{FulfillmentCtxt, NextSolverError},
infer::{
- DbInternerInferExt, InferCtxt, InferOk,
+ DbInternerInferExt, DefineOpaqueTypes, InferCtxt, InferOk, InferResult,
+ at::ToTrace,
snapshot::CombinedSnapshot,
- traits::{Obligation, ObligationCause},
+ traits::{Obligation, ObligationCause, PredicateObligation},
},
inspect::{InspectConfig, InspectGoal, ProofTreeVisitor},
mapping::{ChalkToNextSolver, NextSolverToChalk},
+ obligation_ctxt::ObligationCtxt,
},
traits::{
FnTrait, NextTraitSolveResult, next_trait_solve_canonical_in_ctxt, next_trait_solve_in_ctxt,
},
};
-impl<'db> InferenceContext<'db> {
+impl<'db> InferenceContext<'_, 'db> {
pub(super) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'db>, T>
where
T: rustc_type_ir::TypeFoldable<DbInterner<'db>>,
@@ -77,7 +74,7 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> {
return;
}
- let db = self.ctx.interner;
+ let db = self.ctx.interner();
let goal = inspect_goal.goal();
if self.ctx.predicate_has_self_ty(goal.predicate, self.self_ty)
// We do not push the instantiated forms of goals as it would cause any
@@ -121,9 +118,9 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> {
pub fn could_unify(
db: &dyn HirDatabase,
env: Arc<TraitEnvironment<'_>>,
- tys: &Canonical<(Ty, Ty)>,
+ tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
) -> bool {
- unify(db, env, tys).is_some()
+ could_unify_impl(db, env, tys, |ctxt| ctxt.select_where_possible())
}
/// Check if types unify eagerly making sure there are no unresolved goals.
@@ -133,94 +130,65 @@ pub fn could_unify(
pub fn could_unify_deeply(
db: &dyn HirDatabase,
env: Arc<TraitEnvironment<'_>>,
- tys: &Canonical<(Ty, Ty)>,
+ tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
) -> bool {
- let mut table = InferenceTable::new(db, env);
- let vars = make_substitutions(tys, &mut table);
- let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
- let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
- let ty1_with_vars = table.normalize_associated_types_in(ty1_with_vars);
- let ty2_with_vars = table.normalize_associated_types_in(ty2_with_vars);
- table.select_obligations_where_possible();
- let ty1_with_vars = table.resolve_completely(ty1_with_vars);
- let ty2_with_vars = table.resolve_completely(ty2_with_vars);
- table.unify_deeply(&ty1_with_vars, &ty2_with_vars)
+ could_unify_impl(db, env, tys, |ctxt| ctxt.select_all_or_error())
}
-pub(crate) fn unify(
+fn could_unify_impl(
db: &dyn HirDatabase,
env: Arc<TraitEnvironment<'_>>,
- tys: &Canonical<(Ty, Ty)>,
-) -> Option<Substitution> {
- let mut table = InferenceTable::new(db, env);
- let vars = make_substitutions(tys, &mut table);
- let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
- let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
- if !table.unify(&ty1_with_vars, &ty2_with_vars) {
- return None;
- }
- // default any type vars that weren't unified back to their original bound vars
- // (kind of hacky)
- let find_var = |iv| {
- vars.iter(Interner).position(|v| match v.data(Interner) {
- GenericArgData::Ty(ty) => ty.inference_var(Interner),
- GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
- GenericArgData::Const(c) => c.inference_var(Interner),
- } == Some(iv))
- };
- let fallback = |iv, kind, binder| match kind {
- chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv).map_or_else(
- || TyKind::Error.intern(Interner).cast(Interner),
- |i| BoundVar::new(binder, i).to_ty(Interner).cast(Interner),
- ),
- chalk_ir::VariableKind::Lifetime => find_var(iv).map_or_else(
- || crate::error_lifetime().cast(Interner),
- |i| BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner),
- ),
- chalk_ir::VariableKind::Const(ty) => find_var(iv).map_or_else(
- || crate::unknown_const(ty.clone()).cast(Interner),
- |i| BoundVar::new(binder, i).to_const(Interner, ty.clone()).cast(Interner),
- ),
- };
- Some(Substitution::from_iter(
- Interner,
- vars.iter(Interner).map(|v| table.resolve_with_fallback(v.clone(), &fallback)),
- ))
+ tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
+ select: for<'a, 'db> fn(&mut ObligationCtxt<'a, 'db>) -> Vec<NextSolverError<'db>>,
+) -> bool {
+ let interner = DbInterner::new_with(db, Some(env.krate), env.block);
+ // FIXME(next-solver): I believe this should use `PostAnalysis` (this is only used for IDE things),
+ // but this causes some bug because of our incorrect impl of `type_of_opaque_hir_typeck()` for TAIT
+ // and async blocks.
+ let infcx = interner.infer_ctxt().build(TypingMode::Analysis {
+ defining_opaque_types_and_generators: SolverDefIds::new_from_iter(interner, []),
+ });
+ let cause = ObligationCause::dummy();
+ let at = infcx.at(&cause, env.env);
+ let vars = make_substitutions(tys, &infcx);
+ let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner).to_nextsolver(interner);
+ let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner).to_nextsolver(interner);
+ let mut ctxt = ObligationCtxt::new(&infcx);
+ let can_unify = at
+ .eq(DefineOpaqueTypes::No, ty1_with_vars, ty2_with_vars)
+ .map(|infer_ok| ctxt.register_infer_ok_obligations(infer_ok))
+ .is_ok();
+ can_unify && select(&mut ctxt).is_empty()
}
fn make_substitutions(
- tys: &chalk_ir::Canonical<(chalk_ir::Ty<Interner>, chalk_ir::Ty<Interner>)>,
- table: &mut InferenceTable<'_>,
-) -> chalk_ir::Substitution<Interner> {
- Substitution::from_iter(
+ tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
+ infcx: &InferCtxt<'_>,
+) -> crate::Substitution {
+ let interner = infcx.interner;
+ crate::Substitution::from_iter(
Interner,
tys.binders.iter(Interner).map(|it| match &it.kind {
- chalk_ir::VariableKind::Ty(_) => table.new_type_var().cast(Interner),
+ chalk_ir::VariableKind::Ty(_) => infcx.next_ty_var().to_chalk(interner).cast(Interner),
// FIXME: maybe wrong?
- chalk_ir::VariableKind::Lifetime => table.new_type_var().cast(Interner),
- chalk_ir::VariableKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
+ chalk_ir::VariableKind::Lifetime => {
+ infcx.next_ty_var().to_chalk(interner).cast(Interner)
+ }
+ chalk_ir::VariableKind::Const(_ty) => {
+ infcx.next_const_var().to_chalk(interner).cast(Interner)
+ }
}),
)
}
-bitflags::bitflags! {
- #[derive(Default, Clone, Copy)]
- pub(crate) struct TypeVariableFlags: u8 {
- const DIVERGING = 1 << 0;
- const INTEGER = 1 << 1;
- const FLOAT = 1 << 2;
- }
-}
-
#[derive(Clone)]
pub(crate) struct InferenceTable<'db> {
pub(crate) db: &'db dyn HirDatabase,
- pub(crate) interner: DbInterner<'db>,
pub(crate) trait_env: Arc<TraitEnvironment<'db>>,
- pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>,
+ pub(crate) tait_coercion_table: Option<FxHashMap<InternedOpaqueTyId, Ty<'db>>>,
pub(crate) infer_ctxt: InferCtxt<'db>,
pub(super) fulfillment_cx: FulfillmentCtxt<'db>,
- pub(super) diverging_type_vars: FxHashSet<crate::next_solver::Ty<'db>>,
+ pub(super) diverging_type_vars: FxHashSet<Ty<'db>>,
}
pub(crate) struct InferenceTableSnapshot<'db> {
@@ -236,7 +204,6 @@ impl<'db> InferenceTable<'db> {
});
InferenceTable {
db,
- interner,
trait_env,
tait_coercion_table: None,
fulfillment_cx: FulfillmentCtxt::new(&infer_ctxt),
@@ -245,15 +212,22 @@ impl<'db> InferenceTable<'db> {
}
}
+ #[inline]
+ pub(crate) fn interner(&self) -> DbInterner<'db> {
+ self.infer_ctxt.interner
+ }
+
+ pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'db>) -> bool {
+ self.infer_ctxt.type_is_copy_modulo_regions(self.trait_env.env, ty)
+ }
+
pub(crate) fn type_var_is_sized(&self, self_ty: TyVid) -> bool {
let Some(sized_did) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else {
return true;
};
self.obligations_for_self_ty(self_ty).into_iter().any(|obligation| {
match obligation.predicate.kind().skip_binder() {
- crate::next_solver::PredicateKind::Clause(
- crate::next_solver::ClauseKind::Trait(data),
- ) => data.def_id().0 == sized_did,
+ PredicateKind::Clause(ClauseKind::Trait(data)) => data.def_id().0 == sized_did,
_ => false,
}
})
@@ -309,28 +283,24 @@ impl<'db> InferenceTable<'db> {
}
}
- fn type_matches_expected_vid(
- &self,
- expected_vid: TyVid,
- ty: crate::next_solver::Ty<'db>,
- ) -> bool {
+ fn type_matches_expected_vid(&self, expected_vid: TyVid, ty: Ty<'db>) -> bool {
let ty = self.shallow_resolve(ty);
match ty.kind() {
- crate::next_solver::TyKind::Infer(rustc_type_ir::TyVar(found_vid)) => {
+ TyKind::Infer(rustc_type_ir::TyVar(found_vid)) => {
self.infer_ctxt.root_var(expected_vid) == self.infer_ctxt.root_var(found_vid)
}
_ => false,
}
}
- pub(super) fn set_diverging(&mut self, ty: crate::next_solver::Ty<'db>) {
+ pub(super) fn set_diverging(&mut self, ty: Ty<'db>) {
self.diverging_type_vars.insert(ty);
}
pub(crate) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'db>, T>
where
- T: rustc_type_ir::TypeFoldable<DbInterner<'db>>,
+ T: TypeFoldable<DbInterner<'db>>,
{
// try to resolve obligations before canonicalizing, since this might
// result in new knowledge about variables
@@ -338,26 +308,11 @@ impl<'db> InferenceTable<'db> {
self.infer_ctxt.canonicalize_response(t)
}
- /// Recurses through the given type, normalizing associated types mentioned
- /// in it by replacing them by type variables and registering obligations to
- /// resolve later. This should be done once for every type we get from some
- /// type annotation (e.g. from a let type annotation, field type or function
- /// call). `make_ty` handles this already, but e.g. for field types we need
- /// to do it as well.
- pub(crate) fn normalize_associated_types_in<T, U>(&mut self, ty: T) -> T
- where
- T: ChalkToNextSolver<'db, U>,
- U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
- {
- self.normalize_associated_types_in_ns(ty.to_nextsolver(self.interner))
- .to_chalk(self.interner)
- }
-
// FIXME: We should get rid of this method. We cannot deeply normalize during inference, only when finishing.
// Inference should use shallow normalization (`try_structurally_resolve_type()`) only, when needed.
- pub(crate) fn normalize_associated_types_in_ns<T>(&mut self, ty: T) -> T
+ pub(crate) fn normalize_associated_types_in<T>(&mut self, ty: T) -> T
where
- T: rustc_type_ir::TypeFoldable<DbInterner<'db>> + Clone,
+ T: TypeFoldable<DbInterner<'db>> + Clone,
{
let ty = self.resolve_vars_with_obligations(ty);
self.infer_ctxt
@@ -370,176 +325,130 @@ impl<'db> InferenceTable<'db> {
/// the inference variables
pub(crate) fn eagerly_normalize_and_resolve_shallow_in<T>(&mut self, ty: T) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
+ T: TypeFoldable<DbInterner<'db>>,
{
- fn eagerly_resolve_ty<const N: usize>(
- table: &mut InferenceTable<'_>,
- ty: Ty,
- mut tys: SmallVec<[Ty; N]>,
- ) -> Ty {
- if tys.contains(&ty) {
- return ty;
- }
- tys.push(ty.clone());
-
- match ty.kind(Interner) {
- TyKind::Alias(AliasTy::Projection(proj_ty)) => {
- let ty = table.normalize_projection_ty(proj_ty.clone());
- eagerly_resolve_ty(table, ty, tys)
- }
- TyKind::InferenceVar(..) => {
- let ty = table.resolve_ty_shallow(&ty);
- eagerly_resolve_ty(table, ty, tys)
- }
- _ => ty,
- }
- }
-
- fold_tys_and_consts(
- ty,
- |e, _| match e {
- Either::Left(ty) => {
- Either::Left(eagerly_resolve_ty::<8>(self, ty, SmallVec::new()))
- }
- Either::Right(c) => Either::Right(match &c.data(Interner).value {
- chalk_ir::ConstValue::Concrete(cc) => match &cc.interned {
- crate::ConstScalar::UnevaluatedConst(c_id, subst) => {
- // FIXME: same as `normalize_associated_types_in`
- if subst.len(Interner) == 0 {
- if let Ok(eval) = self.db.const_eval(*c_id, subst.clone(), None) {
- eval
- } else {
- unknown_const(c.data(Interner).ty.clone())
- }
- } else {
- unknown_const(c.data(Interner).ty.clone())
- }
- }
- _ => c,
- },
- _ => c,
- }),
- },
- DebruijnIndex::INNERMOST,
- )
- }
-
- pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
- let ty = TyKind::Alias(chalk_ir::AliasTy::Projection(proj_ty))
- .intern(Interner)
- .to_nextsolver(self.interner);
- self.normalize_alias_ty(ty).to_chalk(self.interner)
- }
-
- pub(crate) fn normalize_alias_ty(
- &mut self,
- alias: crate::next_solver::Ty<'db>,
- ) -> crate::next_solver::Ty<'db> {
- let infer_term = self.infer_ctxt.next_ty_var();
- let obligation = crate::next_solver::Predicate::new(
- self.interner,
- crate::next_solver::Binder::dummy(crate::next_solver::PredicateKind::AliasRelate(
- alias.into(),
- infer_term.into(),
- rustc_type_ir::AliasRelationDirection::Equate,
- )),
- );
- self.register_obligation(obligation);
- self.resolve_vars_with_obligations(infer_term)
- }
-
- fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
- let var = match kind {
- TyVariableKind::General => {
- let var = self.infer_ctxt.next_ty_vid();
- InferenceVar::from(var.as_u32())
- }
- TyVariableKind::Integer => {
- let var = self.infer_ctxt.next_int_vid();
- InferenceVar::from(var.as_u32())
- }
- TyVariableKind::Float => {
- let var = self.infer_ctxt.next_float_vid();
- InferenceVar::from(var.as_u32())
- }
- };
-
- let ty = var.to_ty(Interner, kind);
- if diverging {
- self.diverging_type_vars.insert(ty.to_nextsolver(self.interner));
- }
- ty
+ let ty = self.resolve_vars_with_obligations(ty);
+ let ty = self.normalize_associated_types_in(ty);
+ self.resolve_vars_with_obligations(ty)
}
- pub(crate) fn new_type_var(&mut self) -> Ty {
- self.new_var(TyVariableKind::General, false)
+ pub(crate) fn normalize_alias_ty(&mut self, alias: Ty<'db>) -> Ty<'db> {
+ self.infer_ctxt
+ .at(&ObligationCause::new(), self.trait_env.env)
+ .structurally_normalize_ty(alias, &mut self.fulfillment_cx)
+ .unwrap_or(alias)
}
- pub(crate) fn next_ty_var(&mut self) -> crate::next_solver::Ty<'db> {
+ pub(crate) fn next_ty_var(&mut self) -> Ty<'db> {
self.infer_ctxt.next_ty_var()
}
- pub(crate) fn new_integer_var(&mut self) -> Ty {
- self.new_var(TyVariableKind::Integer, false)
+ pub(crate) fn next_const_var(&mut self) -> Const<'db> {
+ self.infer_ctxt.next_const_var()
}
- pub(crate) fn new_float_var(&mut self) -> Ty {
- self.new_var(TyVariableKind::Float, false)
+ pub(crate) fn next_int_var(&mut self) -> Ty<'db> {
+ self.infer_ctxt.next_int_var()
}
- pub(crate) fn new_maybe_never_var(&mut self) -> Ty {
- self.new_var(TyVariableKind::General, true)
+ pub(crate) fn next_float_var(&mut self) -> Ty<'db> {
+ self.infer_ctxt.next_float_var()
}
- pub(crate) fn new_const_var(&mut self, ty: Ty) -> Const {
- let var = self.infer_ctxt.next_const_vid();
- let var = InferenceVar::from(var.as_u32());
- var.to_const(Interner, ty)
+ pub(crate) fn new_maybe_never_var(&mut self) -> Ty<'db> {
+ let var = self.next_ty_var();
+ self.set_diverging(var);
+ var
}
- pub(crate) fn new_lifetime_var(&mut self) -> Lifetime {
- let var = self.infer_ctxt.next_region_vid();
- let var = InferenceVar::from(var.as_u32());
- var.to_lifetime(Interner)
+ pub(crate) fn next_region_var(&mut self) -> Region<'db> {
+ self.infer_ctxt.next_region_var()
}
- pub(crate) fn next_region_var(&mut self) -> crate::next_solver::Region<'db> {
- self.infer_ctxt.next_region_var()
+ pub(crate) fn next_var_for_param(&mut self, id: GenericParamId) -> GenericArg<'db> {
+ match id {
+ GenericParamId::TypeParamId(_) => self.next_ty_var().into(),
+ GenericParamId::ConstParamId(_) => self.next_const_var().into(),
+ GenericParamId::LifetimeParamId(_) => self.next_region_var().into(),
+ }
}
pub(crate) fn resolve_with_fallback<T>(
&mut self,
t: T,
- fallback: &dyn Fn(InferenceVar, VariableKind, DebruijnIndex) -> GenericArg,
+ fallback_ty: &mut dyn FnMut(DebruijnIndex, InferTy) -> Ty<'db>,
+ fallback_const: &mut dyn FnMut(DebruijnIndex, InferConst) -> Const<'db>,
+ fallback_region: &mut dyn FnMut(DebruijnIndex, RegionVid) -> Region<'db>,
) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
+ T: TypeFoldable<DbInterner<'db>>,
{
- self.resolve_with_fallback_inner(t, &fallback)
- }
+ struct Resolver<'a, 'db> {
+ table: &'a mut InferenceTable<'db>,
+ binder: DebruijnIndex,
+ fallback_ty: &'a mut dyn FnMut(DebruijnIndex, InferTy) -> Ty<'db>,
+ fallback_const: &'a mut dyn FnMut(DebruijnIndex, InferConst) -> Const<'db>,
+ fallback_region: &'a mut dyn FnMut(DebruijnIndex, RegionVid) -> Region<'db>,
+ }
+
+ impl<'db> TypeFolder<DbInterner<'db>> for Resolver<'_, 'db> {
+ fn cx(&self) -> DbInterner<'db> {
+ self.table.interner()
+ }
- pub(crate) fn fresh_subst(&mut self, binders: &[CanonicalVarKind<Interner>]) -> Substitution {
- Substitution::from_iter(
- Interner,
- binders.iter().map(|kind| match &kind.kind {
- chalk_ir::VariableKind::Ty(ty_variable_kind) => {
- self.new_var(*ty_variable_kind, false).cast(Interner)
+ fn fold_binder<T>(&mut self, t: Binder<'db, T>) -> Binder<'db, T>
+ where
+ T: TypeFoldable<DbInterner<'db>>,
+ {
+ self.binder.shift_in(1);
+ let result = t.super_fold_with(self);
+ self.binder.shift_out(1);
+ result
+ }
+
+ fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
+ if !t.has_infer() {
+ return t;
}
- chalk_ir::VariableKind::Lifetime => self.new_lifetime_var().cast(Interner),
- chalk_ir::VariableKind::Const(ty) => self.new_const_var(ty.clone()).cast(Interner),
- }),
- )
- }
- pub(crate) fn instantiate_canonical<T>(&mut self, canonical: Canonical<T>) -> T
- where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + std::fmt::Debug,
- {
- let subst = self.fresh_subst(canonical.binders.as_slice(Interner));
- subst.apply(canonical.value, Interner)
+ if let TyKind::Infer(infer) = t.kind() {
+ (self.fallback_ty)(self.binder, infer)
+ } else {
+ t.super_fold_with(self)
+ }
+ }
+
+ fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
+ if !c.has_infer() {
+ return c;
+ }
+
+ if let ConstKind::Infer(infer) = c.kind() {
+ (self.fallback_const)(self.binder, infer)
+ } else {
+ c.super_fold_with(self)
+ }
+ }
+
+ fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
+ if let RegionKind::ReVar(infer) = r.kind() {
+ (self.fallback_region)(self.binder, infer)
+ } else {
+ r
+ }
+ }
+ }
+
+ t.fold_with(&mut Resolver {
+ table: self,
+ binder: DebruijnIndex::ZERO,
+ fallback_ty,
+ fallback_const,
+ fallback_region,
+ })
}
- pub(crate) fn instantiate_canonical_ns<T>(
+ pub(crate) fn instantiate_canonical<T>(
&mut self,
canonical: rustc_type_ir::Canonical<DbInterner<'db>, T>,
) -> T
@@ -549,112 +458,35 @@ impl<'db> InferenceTable<'db> {
self.infer_ctxt.instantiate_canonical(&canonical).0
}
- fn resolve_with_fallback_inner<T>(
- &mut self,
- t: T,
- fallback: &dyn Fn(InferenceVar, VariableKind, DebruijnIndex) -> GenericArg,
- ) -> T
+ pub(crate) fn resolve_completely<T>(&mut self, value: T) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
+ T: TypeFoldable<DbInterner<'db>>,
{
- let var_stack = &mut vec![];
- t.fold_with(
- &mut resolve::Resolver { table: self, var_stack, fallback },
- DebruijnIndex::INNERMOST,
- )
- }
-
- pub(crate) fn resolve_completely<T, U>(&mut self, t: T) -> T
- where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>,
- U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
- {
- let value = t.to_nextsolver(self.interner);
let value = self.infer_ctxt.resolve_vars_if_possible(value);
let mut goals = vec![];
- let value = value.fold_with(&mut resolve_completely::Resolver::new(self, true, &mut goals));
// FIXME(next-solver): Handle `goals`.
- value.to_chalk(self.interner)
+ value.fold_with(&mut resolve_completely::Resolver::new(self, true, &mut goals))
}
/// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that.
- pub(crate) fn unify<T: ChalkToNextSolver<'db, U>, U: Relate<DbInterner<'db>>>(
- &mut self,
- ty1: &T,
- ty2: &T,
- ) -> bool {
- let result = match self.try_unify(ty1, ty2) {
- Ok(r) => r,
- Err(_) => return false,
- };
- self.register_obligations(result.goals);
- true
- }
-
- pub(crate) fn unify_ns<T: Relate<DbInterner<'db>>>(&mut self, lhs: T, rhs: T) -> bool {
- let Ok(infer_ok) = self.try_unify_ns(lhs, rhs) else {
- return false;
- };
- self.register_obligations(infer_ok.goals);
- true
- }
-
- /// Unify two relatable values (e.g. `Ty`) and check whether trait goals which arise from that could be fulfilled
- pub(crate) fn unify_deeply<T: ChalkToNextSolver<'db, U>, U: Relate<DbInterner<'db>>>(
- &mut self,
- ty1: &T,
- ty2: &T,
- ) -> bool {
- let result = match self.try_unify(ty1, ty2) {
- Ok(r) => r,
- Err(_) => return false,
- };
- result.goals.into_iter().all(|goal| {
- matches!(next_trait_solve_in_ctxt(&self.infer_ctxt, goal), Ok((_, Certainty::Yes)))
- })
+ pub(crate) fn unify<T: ToTrace<'db>>(&mut self, ty1: T, ty2: T) -> bool {
+ self.try_unify(ty1, ty2).map(|infer_ok| self.register_infer_ok(infer_ok)).is_ok()
}
/// Unify two relatable values (e.g. `Ty`) and return new trait goals arising from it, so the
/// caller needs to deal with them.
- pub(crate) fn try_unify<T: ChalkToNextSolver<'db, U>, U: Relate<DbInterner<'db>>>(
- &mut self,
- t1: &T,
- t2: &T,
- ) -> InferResult<'db, ()> {
- let lhs = t1.to_nextsolver(self.interner);
- let rhs = t2.to_nextsolver(self.interner);
- self.try_unify_ns(lhs, rhs)
- }
-
- /// Unify two relatable values (e.g. `Ty`) and return new trait goals arising from it, so the
- /// caller needs to deal with them.
- pub(crate) fn try_unify_ns<T: Relate<DbInterner<'db>>>(
- &mut self,
- lhs: T,
- rhs: T,
- ) -> InferResult<'db, ()> {
- let variance = rustc_type_ir::Variance::Invariant;
- let span = crate::next_solver::Span::dummy();
- match self.infer_ctxt.relate(self.trait_env.env, lhs, variance, rhs, span) {
- Ok(goals) => Ok(crate::infer::InferOk { goals, value: () }),
- Err(_) => Err(TypeError),
- }
- }
-
- /// If `ty` is a type variable with known type, returns that type;
- /// otherwise, return ty.
- #[tracing::instrument(skip(self))]
- pub(crate) fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
- self.shallow_resolve(ty.to_nextsolver(self.interner)).to_chalk(self.interner)
+ pub(crate) fn try_unify<T: ToTrace<'db>>(&mut self, t1: T, t2: T) -> InferResult<'db, ()> {
+ self.infer_ctxt.at(&ObligationCause::new(), self.trait_env.env).eq(
+ DefineOpaqueTypes::Yes,
+ t1,
+ t2,
+ )
}
- pub(crate) fn shallow_resolve(
- &self,
- ty: crate::next_solver::Ty<'db>,
- ) -> crate::next_solver::Ty<'db> {
+ pub(crate) fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {
self.infer_ctxt.shallow_resolve(ty)
}
@@ -662,8 +494,6 @@ impl<'db> InferenceTable<'db> {
where
T: rustc_type_ir::TypeFoldable<DbInterner<'db>>,
{
- use rustc_type_ir::TypeVisitableExt;
-
if !t.has_non_region_infer() {
return t;
}
@@ -678,26 +508,18 @@ impl<'db> InferenceTable<'db> {
self.infer_ctxt.resolve_vars_if_possible(t)
}
- pub(crate) fn structurally_resolve_type(&mut self, ty: &Ty) -> Ty {
- if let TyKind::Alias(chalk_ir::AliasTy::Projection(..)) = ty.kind(Interner) {
- self.structurally_normalize_ty(ty)
- } else {
- self.resolve_vars_with_obligations(ty.to_nextsolver(self.interner))
- .to_chalk(self.interner)
- }
- }
-
- fn structurally_normalize_ty(&mut self, ty: &Ty) -> Ty {
- self.structurally_normalize_term(ty.to_nextsolver(self.interner).into())
- .expect_ty()
- .to_chalk(self.interner)
+ /// Create a `GenericArgs` full of infer vars for `def`.
+ pub(crate) fn fresh_args_for_item(&self, def: SolverDefId) -> GenericArgs<'db> {
+ self.infer_ctxt.fresh_args_for_item(def)
}
- fn structurally_normalize_term(&mut self, term: Term<'db>) -> Term<'db> {
- self.infer_ctxt
- .at(&ObligationCause::new(), self.trait_env.env)
- .structurally_normalize_term(term, &mut self.fulfillment_cx)
- .unwrap_or(term)
+ /// Like `fresh_args_for_item()`, but first uses the args from `first`.
+ pub(crate) fn fill_rest_fresh_args(
+ &self,
+ def_id: SolverDefId,
+ first: impl IntoIterator<Item = GenericArg<'db>>,
+ ) -> GenericArgs<'db> {
+ self.infer_ctxt.fill_rest_fresh_args(def_id, first)
}
/// Try to resolve `ty` to a structural type, normalizing aliases.
@@ -705,11 +527,8 @@ impl<'db> InferenceTable<'db> {
/// In case there is still ambiguity, the returned type may be an inference
/// variable. This is different from `structurally_resolve_type` which errors
/// in this case.
- pub(crate) fn try_structurally_resolve_type(
- &mut self,
- ty: crate::next_solver::Ty<'db>,
- ) -> crate::next_solver::Ty<'db> {
- if let crate::next_solver::TyKind::Alias(..) = ty.kind() {
+ pub(crate) fn try_structurally_resolve_type(&mut self, ty: Ty<'db>) -> Ty<'db> {
+ if let TyKind::Alias(..) = ty.kind() {
// We need to use a separate variable here as otherwise the temporary for
// `self.fulfillment_cx.borrow_mut()` is alive in the `Err` branch, resulting
// in a reentrant borrow, causing an ICE.
@@ -719,13 +538,18 @@ impl<'db> InferenceTable<'db> {
.structurally_normalize_ty(ty, &mut self.fulfillment_cx);
match result {
Ok(normalized_ty) => normalized_ty,
- Err(_errors) => crate::next_solver::Ty::new_error(self.interner, ErrorGuaranteed),
+ Err(_errors) => Ty::new_error(self.interner(), ErrorGuaranteed),
}
} else {
self.resolve_vars_with_obligations(ty)
}
}
+ pub(crate) fn structurally_resolve_type(&mut self, ty: Ty<'db>) -> Ty<'db> {
+ self.try_structurally_resolve_type(ty)
+ // FIXME: Err if it still contain infer vars.
+ }
+
pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot<'db> {
let ctxt_snapshot = self.infer_ctxt.start_snapshot();
let obligations = self.fulfillment_cx.clone();
@@ -794,7 +618,7 @@ impl<'db> InferenceTable<'db> {
self.fulfillment_cx.register_predicate_obligation(
&self.infer_ctxt,
Obligation::new(
- self.interner,
+ self.interner(),
ObligationCause::new(),
goal.param_env,
goal.predicate,
@@ -810,21 +634,11 @@ impl<'db> InferenceTable<'db> {
value
}
- pub(crate) fn register_obligations(
- &mut self,
- obligations: Vec<crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>>,
- ) {
- obligations.into_iter().for_each(|goal| self.register_obligation_in_env(goal));
- }
-
pub(crate) fn select_obligations_where_possible(&mut self) {
self.fulfillment_cx.select_where_possible(&self.infer_ctxt);
}
- pub(super) fn register_predicate(
- &mut self,
- obligation: crate::next_solver::infer::traits::PredicateObligation<'db>,
- ) {
+ pub(super) fn register_predicate(&mut self, obligation: PredicateObligation<'db>) {
if obligation.has_escaping_bound_vars() {
panic!("escaping bound vars in predicate {:?}", obligation);
}
@@ -834,7 +648,7 @@ impl<'db> InferenceTable<'db> {
pub(super) fn register_predicates<I>(&mut self, obligations: I)
where
- I: IntoIterator<Item = crate::next_solver::infer::traits::PredicateObligation<'db>>,
+ I: IntoIterator<Item = PredicateObligation<'db>>,
{
obligations.into_iter().for_each(|obligation| {
self.register_predicate(obligation);
@@ -843,16 +657,14 @@ impl<'db> InferenceTable<'db> {
pub(crate) fn callable_sig(
&mut self,
- ty: &Ty,
+ ty: Ty<'db>,
num_args: usize,
- ) -> Option<(Option<FnTrait>, Vec<crate::next_solver::Ty<'db>>, crate::next_solver::Ty<'db>)>
- {
- match ty.callable_sig(self.db) {
- Some(sig) => Some((
- None,
- sig.params().iter().map(|param| param.to_nextsolver(self.interner)).collect(),
- sig.ret().to_nextsolver(self.interner),
- )),
+ ) -> Option<(Option<FnTrait>, Vec<Ty<'db>>, Ty<'db>)> {
+ match ty.callable_sig(self.interner()) {
+ Some(sig) => {
+ let sig = sig.skip_binder();
+ Some((None, sig.inputs_and_output.inputs().to_vec(), sig.output()))
+ }
None => {
let (f, args_ty, return_ty) = self.callable_sig_from_fn_trait(ty, num_args)?;
Some((Some(f), args_ty, return_ty))
@@ -862,9 +674,9 @@ impl<'db> InferenceTable<'db> {
fn callable_sig_from_fn_trait(
&mut self,
- ty: &Ty,
+ ty: Ty<'db>,
num_args: usize,
- ) -> Option<(FnTrait, Vec<next_solver::Ty<'db>>, next_solver::Ty<'db>)> {
+ ) -> Option<(FnTrait, Vec<Ty<'db>>, Ty<'db>)> {
for (fn_trait_name, output_assoc_name, subtraits) in [
(FnTrait::FnOnce, sym::Output, &[FnTrait::Fn, FnTrait::FnMut][..]),
(FnTrait::AsyncFnMut, sym::CallRefFuture, &[FnTrait::AsyncFn]),
@@ -877,8 +689,8 @@ impl<'db> InferenceTable<'db> {
trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
let mut arg_tys = Vec::with_capacity(num_args);
- let arg_ty = next_solver::Ty::new_tup_from_iter(
- self.interner,
+ let arg_ty = Ty::new_tup_from_iter(
+ self.interner(),
std::iter::repeat_with(|| {
let ty = self.next_ty_var();
arg_tys.push(ty);
@@ -886,24 +698,23 @@ impl<'db> InferenceTable<'db> {
})
.take(num_args),
);
- let args = [ty.to_nextsolver(self.interner), arg_ty];
- let trait_ref = crate::next_solver::TraitRef::new(self.interner, fn_trait.into(), args);
+ let args = [ty, arg_ty];
+ let trait_ref = TraitRef::new(self.interner(), fn_trait.into(), args);
- let projection = crate::next_solver::Ty::new_alias(
- self.interner,
+ let projection = Ty::new_alias(
+ self.interner(),
rustc_type_ir::AliasTyKind::Projection,
- crate::next_solver::AliasTy::new(self.interner, output_assoc_type.into(), args),
+ AliasTy::new(self.interner(), output_assoc_type.into(), args),
);
- let pred = crate::next_solver::Predicate::upcast_from(trait_ref, self.interner);
+ let pred = Predicate::upcast_from(trait_ref, self.interner());
if !self.try_obligation(pred).no_solution() {
self.register_obligation(pred);
let return_ty = self.normalize_alias_ty(projection);
for &fn_x in subtraits {
let fn_x_trait = fn_x.get_id(self.db, krate)?;
- let trait_ref =
- crate::next_solver::TraitRef::new(self.interner, fn_x_trait.into(), args);
- let pred = crate::next_solver::Predicate::upcast_from(trait_ref, self.interner);
+ let trait_ref = TraitRef::new(self.interner(), fn_x_trait.into(), args);
+ let pred = Predicate::upcast_from(trait_ref, self.interner());
if !self.try_obligation(pred).no_solution() {
return Some((fn_x, arg_tys, return_ty));
}
@@ -916,40 +727,53 @@ impl<'db> InferenceTable<'db> {
pub(super) fn insert_type_vars<T>(&mut self, ty: T) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
+ T: TypeFoldable<DbInterner<'db>>,
{
- fold_generic_args(
- ty,
- |arg, _| match arg {
- GenericArgData::Ty(ty) => GenericArgData::Ty(self.insert_type_vars_shallow(ty)),
- // FIXME: insert lifetime vars once LifetimeData::InferenceVar
- // and specific error variant for lifetimes start being constructed
- GenericArgData::Lifetime(lt) => GenericArgData::Lifetime(lt),
- GenericArgData::Const(c) => {
- GenericArgData::Const(self.insert_const_vars_shallow(c))
+ struct Folder<'a, 'db> {
+ table: &'a mut InferenceTable<'db>,
+ }
+ impl<'db> TypeFolder<DbInterner<'db>> for Folder<'_, 'db> {
+ fn cx(&self) -> DbInterner<'db> {
+ self.table.interner()
+ }
+
+ fn fold_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
+ if !ty.references_error() {
+ return ty;
}
- },
- DebruijnIndex::INNERMOST,
- )
- }
- /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
- pub(super) fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
- match ty.kind(Interner) {
- TyKind::Error => self.new_type_var(),
- TyKind::InferenceVar(..) => {
- let ty_resolved = self.structurally_resolve_type(&ty);
- if ty_resolved.is_unknown() { self.new_type_var() } else { ty }
+ if ty.is_ty_error() { self.table.next_ty_var() } else { ty.super_fold_with(self) }
+ }
+
+ fn fold_const(&mut self, ct: Const<'db>) -> Const<'db> {
+ if !ct.references_error() {
+ return ct;
+ }
+
+ if ct.is_ct_error() {
+ self.table.next_const_var()
+ } else {
+ ct.super_fold_with(self)
+ }
+ }
+
+ fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
+ if r.is_error() { self.table.next_region_var() } else { r }
}
- _ => ty,
}
+
+ ty.fold_with(&mut Folder { table: self })
+ }
+
+ /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
+ pub(super) fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> {
+ if ty.is_ty_error() { self.next_ty_var() } else { ty }
}
/// Whenever you lower a user-written type, you should call this.
- pub(crate) fn process_user_written_ty<T, U>(&mut self, ty: T) -> T
+ pub(crate) fn process_user_written_ty<T>(&mut self, ty: T) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>,
- U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
+ T: TypeFoldable<DbInterner<'db>>,
{
self.process_remote_user_written_ty(ty)
// FIXME: Register a well-formed obligation.
@@ -957,10 +781,9 @@ impl<'db> InferenceTable<'db> {
/// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
/// while `process_user_written_ty()` should (but doesn't currently).
- pub(crate) fn process_remote_user_written_ty<T, U>(&mut self, ty: T) -> T
+ pub(crate) fn process_remote_user_written_ty<T>(&mut self, ty: T) -> T
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>,
- U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
+ T: TypeFoldable<DbInterner<'db>>,
{
let ty = self.insert_type_vars(ty);
// See https://github.com/rust-lang/rust/blob/cdb45c87e2cd43495379f7e867e3cc15dcee9f93/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs#L487-L495:
@@ -971,44 +794,33 @@ impl<'db> InferenceTable<'db> {
}
/// Replaces ConstScalar::Unknown by a new type var, so we can maybe still infer it.
- pub(super) fn insert_const_vars_shallow(&mut self, c: Const) -> Const {
- let data = c.data(Interner);
- match &data.value {
- ConstValue::Concrete(cc) => match &cc.interned {
- crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()),
- // try to evaluate unevaluated const. Replace with new var if const eval failed.
- crate::ConstScalar::UnevaluatedConst(id, subst) => {
- if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
- eval
- } else {
- self.new_const_var(data.ty.clone())
- }
- }
- _ => c,
- },
- _ => c,
- }
+ pub(super) fn insert_const_vars_shallow(&mut self, c: Const<'db>) -> Const<'db> {
+ if c.is_ct_error() { self.next_const_var() } else { c }
}
/// Check if given type is `Sized` or not
- pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool {
- fn short_circuit_trivial_tys(ty: &Ty) -> Option<bool> {
- match ty.kind(Interner) {
- TyKind::Scalar(..)
+ pub(crate) fn is_sized(&mut self, ty: Ty<'db>) -> bool {
+ fn short_circuit_trivial_tys(ty: Ty<'_>) -> Option<bool> {
+ match ty.kind() {
+ TyKind::Bool
+ | TyKind::Char
+ | TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
| TyKind::Ref(..)
- | TyKind::Raw(..)
+ | TyKind::RawPtr(..)
| TyKind::Never
| TyKind::FnDef(..)
| TyKind::Array(..)
- | TyKind::Function(..) => Some(true),
- TyKind::Slice(..) | TyKind::Str | TyKind::Dyn(..) => Some(false),
+ | TyKind::FnPtr(..) => Some(true),
+ TyKind::Slice(..) | TyKind::Str | TyKind::Dynamic(..) => Some(false),
_ => None,
}
}
- let mut ty = ty.clone();
+ let mut ty = ty;
ty = self.eagerly_normalize_and_resolve_shallow_in(ty);
- if let Some(sized) = short_circuit_trivial_tys(&ty) {
+ if let Some(sized) = short_circuit_trivial_tys(ty) {
return sized;
}
@@ -1019,9 +831,8 @@ 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(id.into())[last_field]
- .clone()
- .substitute(Interner, subst);
+ let last_field_ty = self.db.field_types_ns(id.into())[last_field]
+ .instantiate(self.interner(), subst);
if structs.contains(&ty) {
// A struct recursively contains itself as a tail field somewhere.
return true; // Don't overload the users with too many errors.
@@ -1031,7 +842,7 @@ impl<'db> InferenceTable<'db> {
// as unsized by the chalk, so we do this manually.
ty = last_field_ty;
ty = self.eagerly_normalize_and_resolve_shallow_in(ty);
- if let Some(sized) = short_circuit_trivial_tys(&ty) {
+ if let Some(sized) = short_circuit_trivial_tys(ty) {
return sized;
}
} else {
@@ -1044,8 +855,8 @@ impl<'db> InferenceTable<'db> {
return false;
};
let sized_pred = Predicate::upcast_from(
- TraitRef::new(self.interner, sized.into(), [ty.to_nextsolver(self.interner)]),
- self.interner,
+ TraitRef::new(self.interner(), sized.into(), [ty]),
+ self.interner(),
);
self.try_obligation(sized_pred).certain()
}
@@ -1060,189 +871,14 @@ impl fmt::Debug for InferenceTable<'_> {
}
}
-mod resolve {
- use super::InferenceTable;
- use crate::{
- Const, DebruijnIndex, GenericArg, InferenceVar, Interner, Lifetime, Ty, TyVariableKind,
- VariableKind, next_solver::mapping::NextSolverToChalk,
- };
- use chalk_ir::fold::{TypeFoldable, TypeFolder};
- use rustc_type_ir::{FloatVid, IntVid, TyVid};
-
- #[derive(Debug, Copy, Clone, PartialEq, Eq)]
- pub(super) enum VarKind {
- Ty(TyVariableKind),
- Const,
- }
-
- #[derive(chalk_derive::FallibleTypeFolder)]
- #[has_interner(Interner)]
- pub(super) struct Resolver<
- 'a,
- 'b,
- F: Fn(InferenceVar, VariableKind, DebruijnIndex) -> GenericArg,
- > {
- pub(super) table: &'a mut InferenceTable<'b>,
- pub(super) var_stack: &'a mut Vec<(InferenceVar, VarKind)>,
- pub(super) fallback: F,
- }
- impl<F> TypeFolder<Interner> for Resolver<'_, '_, F>
- where
- F: Fn(InferenceVar, VariableKind, DebruijnIndex) -> GenericArg,
- {
- fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
-
- fn fold_inference_ty(
- &mut self,
- var: InferenceVar,
- kind: TyVariableKind,
- outer_binder: DebruijnIndex,
- ) -> Ty {
- match kind {
- TyVariableKind::General => {
- let vid = self.table.infer_ctxt.root_var(TyVid::from(var.index()));
- let var = InferenceVar::from(vid.as_u32());
- if self.var_stack.contains(&(var, VarKind::Ty(kind))) {
- // recursive type
- return (self.fallback)(var, VariableKind::Ty(kind), outer_binder)
- .assert_ty_ref(Interner)
- .clone();
- }
- if let Ok(known_ty) = self.table.infer_ctxt.probe_ty_var(vid) {
- let known_ty: Ty = known_ty.to_chalk(self.table.interner);
- // known_ty may contain other variables that are known by now
- self.var_stack.push((var, VarKind::Ty(kind)));
- let result = known_ty.fold_with(self, outer_binder);
- self.var_stack.pop();
- result
- } else {
- (self.fallback)(var, VariableKind::Ty(kind), outer_binder)
- .assert_ty_ref(Interner)
- .clone()
- }
- }
- TyVariableKind::Integer => {
- let vid = self
- .table
- .infer_ctxt
- .inner
- .borrow_mut()
- .int_unification_table()
- .find(IntVid::from(var.index()));
- let var = InferenceVar::from(vid.as_u32());
- if self.var_stack.contains(&(var, VarKind::Ty(kind))) {
- // recursive type
- return (self.fallback)(var, VariableKind::Ty(kind), outer_binder)
- .assert_ty_ref(Interner)
- .clone();
- }
- if let Some(known_ty) = self.table.infer_ctxt.resolve_int_var(vid) {
- let known_ty: Ty = known_ty.to_chalk(self.table.interner);
- // known_ty may contain other variables that are known by now
- self.var_stack.push((var, VarKind::Ty(kind)));
- let result = known_ty.fold_with(self, outer_binder);
- self.var_stack.pop();
- result
- } else {
- (self.fallback)(var, VariableKind::Ty(kind), outer_binder)
- .assert_ty_ref(Interner)
- .clone()
- }
- }
- TyVariableKind::Float => {
- let vid = self
- .table
- .infer_ctxt
- .inner
- .borrow_mut()
- .float_unification_table()
- .find(FloatVid::from(var.index()));
- let var = InferenceVar::from(vid.as_u32());
- if self.var_stack.contains(&(var, VarKind::Ty(kind))) {
- // recursive type
- return (self.fallback)(var, VariableKind::Ty(kind), outer_binder)
- .assert_ty_ref(Interner)
- .clone();
- }
- if let Some(known_ty) = self.table.infer_ctxt.resolve_float_var(vid) {
- let known_ty: Ty = known_ty.to_chalk(self.table.interner);
- // known_ty may contain other variables that are known by now
- self.var_stack.push((var, VarKind::Ty(kind)));
- let result = known_ty.fold_with(self, outer_binder);
- self.var_stack.pop();
- result
- } else {
- (self.fallback)(var, VariableKind::Ty(kind), outer_binder)
- .assert_ty_ref(Interner)
- .clone()
- }
- }
- }
- }
-
- fn fold_inference_const(
- &mut self,
- ty: Ty,
- var: InferenceVar,
- outer_binder: DebruijnIndex,
- ) -> Const {
- let vid = self
- .table
- .infer_ctxt
- .root_const_var(rustc_type_ir::ConstVid::from_u32(var.index()));
- let var = InferenceVar::from(vid.as_u32());
- if self.var_stack.contains(&(var, VarKind::Const)) {
- // recursive
- return (self.fallback)(var, VariableKind::Const(ty), outer_binder)
- .assert_const_ref(Interner)
- .clone();
- }
- if let Ok(known_const) = self.table.infer_ctxt.probe_const_var(vid) {
- let known_const: Const = known_const.to_chalk(self.table.interner);
- // known_ty may contain other variables that are known by now
- self.var_stack.push((var, VarKind::Const));
- let result = known_const.fold_with(self, outer_binder);
- self.var_stack.pop();
- result
- } else {
- (self.fallback)(var, VariableKind::Const(ty), outer_binder)
- .assert_const_ref(Interner)
- .clone()
- }
- }
-
- fn fold_inference_lifetime(
- &mut self,
- _var: InferenceVar,
- _outer_binder: DebruijnIndex,
- ) -> Lifetime {
- // fall back all lifetimes to 'error -- currently we don't deal
- // with any lifetimes, but we can sometimes get some lifetime
- // variables through Chalk's unification, and this at least makes
- // sure we don't leak them outside of inference
- crate::error_lifetime()
- }
- }
-}
-
mod resolve_completely {
- use rustc_type_ir::{
- DebruijnIndex, Flags, TypeFolder, TypeSuperFoldable,
- inherent::{Const as _, Ty as _},
- };
+ use rustc_type_ir::{DebruijnIndex, Flags, TypeFolder, TypeSuperFoldable};
- use crate::next_solver::Region;
use crate::{
infer::unify::InferenceTable,
next_solver::{
- Const, DbInterner, ErrorGuaranteed, Goal, Predicate, Term, Ty,
- infer::traits::ObligationCause,
+ Const, DbInterner, Goal, Predicate, Region, Term, Ty,
+ infer::{resolve::ReplaceInferWithError, traits::ObligationCause},
normalize::deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals,
},
};
@@ -1291,17 +927,17 @@ mod resolve_completely {
value
};
- value.fold_with(&mut ReplaceInferWithError { interner: self.ctx.interner })
+ value.fold_with(&mut ReplaceInferWithError::new(self.ctx.interner()))
}
}
impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Resolver<'cx, 'db> {
fn cx(&self) -> DbInterner<'db> {
- self.ctx.interner
+ self.ctx.interner()
}
fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
- if r.is_var() { Region::error(self.ctx.interner) } else { r }
+ if r.is_var() { Region::error(self.ctx.interner()) } else { r }
}
fn fold_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
@@ -1320,34 +956,4 @@ mod resolve_completely {
predicate.super_fold_with(self)
}
}
-
- struct ReplaceInferWithError<'db> {
- interner: DbInterner<'db>,
- }
-
- impl<'db> TypeFolder<DbInterner<'db>> for ReplaceInferWithError<'db> {
- fn cx(&self) -> DbInterner<'db> {
- self.interner
- }
-
- fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
- if t.is_infer() {
- Ty::new_error(self.interner, ErrorGuaranteed)
- } else {
- t.super_fold_with(self)
- }
- }
-
- fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
- if c.is_ct_infer() {
- Const::new_error(self.interner, ErrorGuaranteed)
- } else {
- c.super_fold_with(self)
- }
- }
-
- fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
- if r.is_var() { Region::error(self.interner) } else { r }
- }
- }
}
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 4071b9a1d5..d97d2af080 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -19,15 +19,13 @@ use rustc_type_ir::{
};
use triomphe::Arc;
-use crate::utils::ClosureSubst;
use crate::{
- Interner, TraitEnvironment,
+ TraitEnvironment,
consteval_nextsolver::try_const_usize,
db::HirDatabase,
next_solver::{
DbInterner, GenericArgs, ParamEnv, Ty, TyKind, TypingMode,
infer::{DbInternerInferExt, traits::ObligationCause},
- mapping::{ChalkToNextSolver, convert_args_for_result},
},
};
@@ -325,19 +323,12 @@ pub fn layout_of_ty_query<'db>(
TyKind::Closure(id, args) => {
let def = db.lookup_intern_closure(id.0);
let infer = db.infer(def.0);
- let (captures, _) = infer.closure_info(&id.0.into());
+ let (captures, _) = infer.closure_info(id.0);
let fields = captures
.iter()
.map(|it| {
- let ty = it
- .ty
- .clone()
- .substitute(
- Interner,
- &ClosureSubst(&convert_args_for_result(interner, args.inner()))
- .parent_subst(db),
- )
- .to_nextsolver(interner);
+ let ty =
+ it.ty.instantiate(interner, args.split_closure_args_untupled().parent_args);
db.layout_of_ty(ty, trait_env.clone())
})
.collect::<Result<Vec<_>, _>>()?;
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index 6960e230a6..d6f0ed3dc0 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -3,7 +3,7 @@ use either::Either;
use hir_def::db::DefDatabase;
use project_model::{Sysroot, toolchain_info::QueryConfig};
use rustc_hash::FxHashMap;
-use rustc_type_ir::inherent::{GenericArgs as _, Ty as _};
+use rustc_type_ir::inherent::GenericArgs as _;
use syntax::ToSmolStr;
use test_fixture::WithFixture;
use triomphe::Arc;
@@ -11,7 +11,7 @@ use triomphe::Arc;
use crate::{
db::HirDatabase,
layout::{Layout, LayoutError},
- next_solver::{AdtDef, DbInterner, GenericArgs, mapping::ChalkToNextSolver},
+ next_solver::{DbInterner, GenericArgs},
setup_tracing,
test_db::TestDB,
};
@@ -84,7 +84,7 @@ fn eval_goal(
let goal_ty = match adt_or_type_alias_id {
Either::Left(adt_id) => crate::next_solver::Ty::new_adt(
interner,
- AdtDef::new(adt_id, interner),
+ adt_id,
GenericArgs::identity_for_item(interner, adt_id.into()),
),
Either::Right(ty_id) => db.ty(ty_id.into()).instantiate_identity(),
@@ -133,11 +133,8 @@ fn eval_expr(
.unwrap()
.0;
let infer = db.infer(function_id.into());
- let goal_ty = infer.type_of_binding[b].clone();
- salsa::attach(&db, || {
- let interner = DbInterner::new_with(&db, None, None);
- db.layout_of_ty(goal_ty.to_nextsolver(interner), db.trait_environment(function_id.into()))
- })
+ let goal_ty = infer.type_of_binding[b];
+ salsa::attach(&db, || db.layout_of_ty(goal_ty, db.trait_environment(function_id.into())))
}
#[track_caller]
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 281cf6b2d4..2aa9b8fa19 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -64,7 +64,6 @@ use chalk_ir::{
fold::{Shift, TypeFoldable},
interner::HasInterner,
};
-use either::Either;
use hir_def::{CallableDefId, GeneralConstId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness};
use hir_expand::name::Name;
use indexmap::{IndexMap, map::Entry};
@@ -233,7 +232,7 @@ impl ComplexMemoryMap<'_> {
}
impl<'db> MemoryMap<'db> {
- pub fn vtable_ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>, MirEvalError> {
+ pub fn vtable_ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>, MirEvalError<'db>> {
match self {
MemoryMap::Empty | MemoryMap::Simple(_) => Err(MirEvalError::InvalidVTableId(id)),
MemoryMap::Complex(cm) => cm.vtable.ty(id),
@@ -249,8 +248,8 @@ impl<'db> MemoryMap<'db> {
/// allocator function as `f` and it will return a mapping of old addresses to new addresses.
fn transform_addresses(
&self,
- mut f: impl FnMut(&[u8], usize) -> Result<usize, MirEvalError>,
- ) -> Result<FxHashMap<usize, usize>, MirEvalError> {
+ mut f: impl FnMut(&[u8], usize) -> Result<usize, MirEvalError<'db>>,
+ ) -> Result<FxHashMap<usize, usize>, MirEvalError<'db>> {
let mut transform = |(addr, val): (&usize, &[u8])| {
let addr = *addr;
let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) };
@@ -646,7 +645,7 @@ impl TypeFoldable<Interner> for CallableSig {
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum ImplTraitId {
- ReturnTypeImplTrait(hir_def::FunctionId, ImplTraitIdx),
+ ReturnTypeImplTrait(hir_def::FunctionId, ImplTraitIdx), // FIXME(next-solver): Should be crate::nextsolver::ImplTraitIdx.
TypeAliasImplTrait(hir_def::TypeAliasId, ImplTraitIdx),
AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
}
@@ -713,102 +712,6 @@ pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<
t.fold_with(&mut FreeVarFolder(for_ty, for_const), DebruijnIndex::INNERMOST)
}
-pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
- t: T,
- mut for_ty: impl FnMut(Ty, DebruijnIndex) -> Ty,
- binders: DebruijnIndex,
-) -> T {
- fold_tys_and_consts(
- t,
- |x, d| match x {
- Either::Left(x) => Either::Left(for_ty(x, d)),
- Either::Right(x) => Either::Right(x),
- },
- binders,
- )
-}
-
-pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
- t: T,
- f: impl FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>,
- binders: DebruijnIndex,
-) -> T {
- use chalk_ir::fold::{TypeFolder, TypeSuperFoldable};
- #[derive(chalk_derive::FallibleTypeFolder)]
- #[has_interner(Interner)]
- struct TyFolder<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>>(F);
- impl<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>> TypeFolder<Interner>
- for TyFolder<F>
- {
- fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
-
- fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty {
- let ty = ty.super_fold_with(self.as_dyn(), outer_binder);
- self.0(Either::Left(ty), outer_binder).left().unwrap()
- }
-
- fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const {
- self.0(Either::Right(c), outer_binder).right().unwrap()
- }
- }
- t.fold_with(&mut TyFolder(f), binders)
-}
-
-pub(crate) fn fold_generic_args<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
- t: T,
- f: impl FnMut(GenericArgData, DebruijnIndex) -> GenericArgData,
- binders: DebruijnIndex,
-) -> T {
- use chalk_ir::fold::{TypeFolder, TypeSuperFoldable};
- #[derive(chalk_derive::FallibleTypeFolder)]
- #[has_interner(Interner)]
- struct TyFolder<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData>(F);
- impl<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData> TypeFolder<Interner>
- for TyFolder<F>
- {
- fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
-
- fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty {
- let ty = ty.super_fold_with(self.as_dyn(), outer_binder);
- self.0(GenericArgData::Ty(ty), outer_binder)
- .intern(Interner)
- .ty(Interner)
- .unwrap()
- .clone()
- }
-
- fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const {
- self.0(GenericArgData::Const(c), outer_binder)
- .intern(Interner)
- .constant(Interner)
- .unwrap()
- .clone()
- }
-
- fn fold_lifetime(&mut self, lt: Lifetime, outer_binder: DebruijnIndex) -> Lifetime {
- let lt = lt.super_fold_with(self.as_dyn(), outer_binder);
- self.0(GenericArgData::Lifetime(lt), outer_binder)
- .intern(Interner)
- .lifetime(Interner)
- .unwrap()
- .clone()
- }
- }
- t.fold_with(&mut TyFolder(f), binders)
-}
-
/// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
/// ensures there are no unbound variables or inference variables anywhere in
/// the `t`.
@@ -942,31 +845,31 @@ pub fn callable_sig_from_fn_trait<'db>(
// - Self: FnOnce<?args_ty>
// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
let args_ty = table.next_ty_var();
- let args = [self_ty.to_nextsolver(table.interner), args_ty];
- let trait_ref = crate::next_solver::TraitRef::new(table.interner, fn_once_trait.into(), args);
+ let args = [self_ty.to_nextsolver(table.interner()), 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(
- table.interner,
+ table.interner(),
rustc_type_ir::AliasTyKind::Projection,
- crate::next_solver::AliasTy::new(table.interner, output_assoc_type.into(), args),
+ crate::next_solver::AliasTy::new(table.interner(), output_assoc_type.into(), args),
);
- let pred = crate::next_solver::Predicate::upcast_from(trait_ref, table.interner);
+ let pred = crate::next_solver::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);
+ crate::next_solver::TraitRef::new(table.interner(), fn_x_trait.into(), args);
if !table
.try_obligation(crate::next_solver::Predicate::upcast_from(
trait_ref,
- table.interner,
+ table.interner(),
))
.no_solution()
{
- let ret_ty = table.resolve_completely(return_ty.to_chalk(table.interner));
- let args_ty = table.resolve_completely(args_ty.to_chalk(table.interner));
+ let ret_ty = table.resolve_completely(return_ty).to_chalk(table.interner());
+ let args_ty = table.resolve_completely(args_ty).to_chalk(table.interner());
let params = args_ty
.as_tuple()?
.iter(Interner)
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 0c197b2703..a9b523a4a6 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -25,14 +25,14 @@ use chalk_ir::{
use either::Either;
use hir_def::{
AdtId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId,
- GenericParamId, ItemContainerId, LocalFieldId, Lookup, StaticId, StructId, TypeAliasId,
- TypeOrConstParamId, UnionId, VariantId,
+ GenericParamId, LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId,
+ UnionId, VariantId,
builtin_type::BuiltinType,
expr_store::{ExpressionStore, path::Path},
hir::generics::{GenericParamDataRef, TypeOrConstParamData, WherePredicate},
lang_item::LangItem,
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
- signatures::{FunctionSignature, TraitFlags},
+ signatures::TraitFlags,
type_ref::{
ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier, TypeBound, TypeRef,
TypeRefId,
@@ -125,26 +125,6 @@ pub enum LifetimeElisionKind {
impl LifetimeElisionKind {
#[inline]
- pub(crate) fn for_const(const_parent: ItemContainerId) -> LifetimeElisionKind {
- match const_parent {
- ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
- LifetimeElisionKind::Elided(static_lifetime())
- }
- ItemContainerId::ImplId(_) => {
- LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true }
- }
- ItemContainerId::TraitId(_) => {
- LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false }
- }
- }
- }
-
- #[inline]
- pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind {
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() }
- }
-
- #[inline]
pub(crate) fn for_fn_ret() -> LifetimeElisionKind {
// FIXME: We should use the elided lifetime here, or `ElisionFailure`.
LifetimeElisionKind::Elided(error_lifetime())
@@ -268,7 +248,7 @@ pub enum ParamLoweringMode {
Variable,
}
-impl<'a> TyLoweringContext<'a> {
+impl<'db> TyLoweringContext<'db> {
pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty {
self.lower_ty_ext(type_ref).0
}
@@ -512,7 +492,7 @@ impl<'a> TyLoweringContext<'a> {
}
#[inline]
- fn on_path_diagnostic_callback(type_ref: TypeRefId) -> PathDiagnosticCallback<'static> {
+ fn on_path_diagnostic_callback<'a>(type_ref: TypeRefId) -> PathDiagnosticCallback<'a, 'db> {
PathDiagnosticCallback {
data: Either::Left(PathDiagnosticCallbackData(type_ref)),
callback: |data, this, diag| {
@@ -523,7 +503,7 @@ impl<'a> TyLoweringContext<'a> {
}
#[inline]
- fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a> {
+ fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'db> {
PathLoweringContext::new(
self,
Self::on_path_diagnostic_callback(path_id.type_ref()),
@@ -559,7 +539,7 @@ impl<'a> TyLoweringContext<'a> {
&mut self,
path_id: PathId,
explicit_self_ty: Ty,
- ) -> Option<(TraitRef, PathLoweringContext<'_, 'a>)> {
+ ) -> Option<(TraitRef, PathLoweringContext<'_, '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.
@@ -576,7 +556,7 @@ impl<'a> TyLoweringContext<'a> {
&'b mut self,
where_predicate: &'b WherePredicate,
ignore_bindings: bool,
- ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
+ ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'db, 'b> {
match where_predicate {
WherePredicate::ForLifetime { target, bound, .. }
| WherePredicate::TypeBound { target, bound } => {
@@ -598,7 +578,7 @@ impl<'a> TyLoweringContext<'a> {
bound: &'b TypeBound,
self_ty: Ty,
ignore_bindings: bool,
- ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
+ ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'db> {
let mut assoc_bounds = None;
let mut clause = None;
match bound {
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index da9dd21183..cdac1c9829 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -3,15 +3,15 @@
use chalk_ir::{BoundVar, cast::Cast, fold::Shift};
use either::Either;
use hir_def::{
- GenericDefId, GenericParamId, Lookup, TraitId,
+ GenericDefId, GenericParamId, TraitId,
expr_store::{
- ExpressionStore, HygieneId,
+ ExpressionStore,
path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments},
},
hir::generics::{
GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
},
- resolver::{ResolveValueResult, TypeNs, ValueNs},
+ resolver::TypeNs,
signatures::TraitFlags,
type_ref::{TypeRef, TypeRefId},
};
@@ -22,7 +22,7 @@ use crate::{
AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, IncorrectGenericsLenKind,
Interner, ParamLoweringMode, PathGenericsSource, PathLoweringDiagnostic, ProjectionTy,
QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind,
- TyLoweringContext, ValueTyDefId, WhereClause,
+ TyLoweringContext, WhereClause,
consteval::{unknown_const, unknown_const_as_generic},
db::HirDatabase,
error_lifetime,
@@ -36,21 +36,22 @@ use crate::{
utils::associated_type_by_name_including_super_traits,
};
-type CallbackData<'a> = Either<
+type CallbackData<'a, 'db> = Either<
super::PathDiagnosticCallbackData,
- crate::infer::diagnostics::PathDiagnosticCallbackData<'a>,
+ 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> {
- pub(crate) data: CallbackData<'a>,
- pub(crate) callback: fn(&CallbackData<'_>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic),
+pub(crate) struct PathDiagnosticCallback<'a, 'db> {
+ pub(crate) data: CallbackData<'a, 'db>,
+ pub(crate) callback:
+ fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic),
}
pub(crate) struct PathLoweringContext<'a, 'b> {
ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a>,
+ on_diagnostic: PathDiagnosticCallback<'a, 'b>,
path: &'a Path,
segments: PathSegments<'a>,
current_segment_idx: usize,
@@ -62,7 +63,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
#[inline]
pub(crate) fn new(
ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a>,
+ on_diagnostic: PathDiagnosticCallback<'a, 'b>,
path: &'a Path,
) -> Self {
let segments = path.segments();
@@ -110,20 +111,6 @@ 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,
@@ -390,103 +377,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
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, _, _) => {
- self.handle_type_ns_resolution(resolution);
- }
- };
- Some(res)
- }
-
fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty {
let Some(res) = res else {
return TyKind::Error.intern(Interner);
@@ -556,62 +446,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
self.ctx.db.ty(typeable).instantiate(interner, args).to_chalk(interner)
}
- /// 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,
- ) -> Substitution {
- 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 Substitution::empty(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,
diff --git a/crates/hir-ty/src/lower_nextsolver.rs b/crates/hir-ty/src/lower_nextsolver.rs
index 84cd216b81..98881004bb 100644
--- a/crates/hir-ty/src/lower_nextsolver.rs
+++ b/crates/hir-ty/src/lower_nextsolver.rs
@@ -17,6 +17,7 @@ use std::{
use base_db::Crate;
use either::Either;
+use hir_def::hir::generics::GenericParamDataRef;
use hir_def::item_tree::FieldsShape;
use hir_def::{
AdtId, AssocItemId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId,
@@ -35,9 +36,9 @@ use hir_def::{
TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId,
},
};
-use hir_def::{ConstId, StaticId};
+use hir_def::{ConstId, LifetimeParamId, StaticId, TypeParamId};
use hir_expand::name::Name;
-use intern::sym;
+use intern::{Symbol, sym};
use la_arena::{Arena, ArenaMap, Idx};
use path::{PathDiagnosticCallback, PathLoweringContext, builtin};
use rustc_ast_ir::Mutability;
@@ -50,12 +51,14 @@ use rustc_type_ir::{
TypeVisitableExt,
inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _},
};
+use rustc_type_ir::{TypeFoldable, TypeFolder, Upcast};
use salsa::plumbing::AsId;
use smallvec::{SmallVec, smallvec};
use stdx::never;
use triomphe::Arc;
use crate::ValueTyDefId;
+use crate::next_solver::ParamConst;
use crate::{
FnAbi, ImplTraitId, Interner, ParamKind, TraitEnvironment, TyDefId, TyLoweringDiagnostic,
TyLoweringDiagnosticKind,
@@ -79,11 +82,11 @@ pub struct ImplTraits<'db> {
}
#[derive(PartialEq, Eq, Debug, Hash)]
-pub(crate) struct ImplTrait<'db> {
+pub struct ImplTrait<'db> {
pub(crate) predicates: Vec<Clause<'db>>,
}
-pub(crate) type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>;
+pub type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>;
#[derive(Debug, Default)]
struct ImplTraitLoweringState<'db> {
@@ -184,6 +187,8 @@ pub(crate) struct TyLoweringContext<'db, 'a> {
pub(crate) unsized_types: FxHashSet<Ty<'db>>,
pub(crate) diagnostics: Vec<TyLoweringDiagnostic>,
lifetime_elision: LifetimeElisionKind<'db>,
+ /// We disallow referencing generic parameters that have an index greater than or equal to this number.
+ disallow_params_after: u32,
}
impl<'db, 'a> TyLoweringContext<'db, 'a> {
@@ -208,6 +213,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
unsized_types: FxHashSet::default(),
diagnostics: Vec::new(),
lifetime_elision,
+ disallow_params_after: u32::MAX,
}
}
@@ -243,6 +249,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self
}
+ pub(crate) fn disallow_params_after(&mut self, after: u32) {
+ self.disallow_params_after = after;
+ }
+
pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind });
}
@@ -265,7 +275,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.lower_ty_ext(type_ref).0
}
- pub(crate) fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty<'db>) -> Const<'db> {
+ 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) => {
@@ -323,6 +333,33 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.generics.get_or_init(|| generics(self.db, self.def))
}
+ fn type_param(&mut self, id: TypeParamId, index: u32, name: Symbol) -> Ty<'db> {
+ if index >= self.disallow_params_after {
+ // FIXME: Report an error.
+ Ty::new_error(self.interner, ErrorGuaranteed)
+ } else {
+ Ty::new_param(self.interner, id, index, name)
+ }
+ }
+
+ fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> {
+ if index >= self.disallow_params_after {
+ // 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 index >= self.disallow_params_after {
+ // FIXME: Report an error.
+ Region::error(self.interner)
+ } else {
+ Region::new_early_param(self.interner, EarlyParamRegion { id, index })
+ }
+ }
+
#[tracing::instrument(skip(self), ret)]
pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) {
let interner = self.interner;
@@ -351,8 +388,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
TypeOrConstParamData::TypeParamData(ty) => ty,
_ => unreachable!(),
};
- Ty::new_param(
- self.interner,
+ self.type_param(
type_param_id,
idx as u32,
type_data
@@ -367,7 +403,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
TypeRef::Array(array) => {
let inner_ty = self.lower_ty(array.ty);
- let const_len = self.lower_const(&array.len, Ty::new_usize(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) => {
@@ -491,7 +527,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
#[inline]
- fn on_path_diagnostic_callback(type_ref: TypeRefId) -> PathDiagnosticCallback<'static, 'db> {
+ fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> {
PathDiagnosticCallback {
data: Either::Left(PathDiagnosticCallbackData(type_ref)),
callback: |data, this, diag| {
@@ -515,7 +551,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
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);
+ return ctx.lower_ty_relative_path(ty, res, false);
}
let mut ctx = self.at_path(path_id);
@@ -545,7 +581,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
TypeNs::TraitId(tr) => tr,
_ => return None,
};
- Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty), ctx))
+ Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx))
}
fn lower_trait_ref(
@@ -869,7 +905,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
ImplTrait { predicates }
}
- pub(crate) fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Region<'db> {
+ 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),
@@ -878,10 +914,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
None => return Region::error(self.interner),
Some(idx) => idx,
};
- Region::new_early_param(
- self.interner,
- EarlyParamRegion { index: idx as u32, id },
- )
+ self.region_param(id, idx as u32)
}
},
None => Region::error(self.interner),
@@ -983,7 +1016,7 @@ pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBind
TyDefId::BuiltinType(it) => EarlyBinder::bind(builtin(interner, it)),
TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt(
interner,
- AdtDef::new(it, interner),
+ it,
GenericArgs::identity_for_item(interner, it.into()),
)),
TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0,
@@ -1748,6 +1781,113 @@ pub(crate) fn lower_generic_arg<'a, 'db, T>(
}
}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct GenericDefaults<'db>(
+ Option<Arc<[Option<EarlyBinder<'db, crate::next_solver::GenericArg<'db>>>]>>,
+);
+
+impl<'db> GenericDefaults<'db> {
+ #[inline]
+ pub fn get(&self, idx: usize) -> Option<EarlyBinder<'db, crate::next_solver::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, id, p, &generic_params);
+ 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);
+ 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,
+ id: GenericParamId,
+ p: GenericParamDataRef<'_>,
+ generic_params: &Generics,
+ ) -> (Option<EarlyBinder<'db, crate::next_solver::GenericArg<'db>>>, bool) {
+ // Each default can only refer to previous parameters.
+ // Type variable default referring to parameter coming
+ // after it is forbidden.
+ ctx.disallow_params_after(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 GenericParamId::ConstParamId(id) = id else {
+ unreachable!("Unexpected lifetime or type argument")
+ };
+
+ let mut 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,
@@ -1804,7 +1944,7 @@ fn fn_sig_for_fn<'db>(
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, AdtDef::new(adt, interner), args);
+ let ty = Ty::new_adt(interner, adt, args);
EarlyBinder::bind(ty)
}
diff --git a/crates/hir-ty/src/lower_nextsolver/path.rs b/crates/hir-ty/src/lower_nextsolver/path.rs
index 0a9f34c9da..babc39694f 100644
--- a/crates/hir-ty/src/lower_nextsolver/path.rs
+++ b/crates/hir-ty/src/lower_nextsolver/path.rs
@@ -51,15 +51,17 @@ use super::{
const_param_ty_query, ty_query,
};
-type CallbackData<'a> =
- Either<PathDiagnosticCallbackData, crate::infer::diagnostics::PathDiagnosticCallbackData<'a>>;
+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>,
+ pub(crate) data: CallbackData<'a, 'db>,
pub(crate) callback:
- fn(&CallbackData<'_>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic),
+ fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic),
}
pub(crate) struct PathLoweringContext<'a, 'b, 'db> {
@@ -155,13 +157,14 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
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), None)
+ (self.select_associated_type(res, infer_args), None)
}
_ => {
// FIXME report error (ambiguous associated type)
@@ -204,6 +207,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
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();
@@ -276,8 +280,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
GenericParamDataRef::TypeParamData(p) => p,
_ => unreachable!(),
};
- Ty::new_param(
- self.ctx.interner,
+ self.ctx.type_param(
param_id,
idx as u32,
p.name
@@ -293,7 +296,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
self.ctx.interner,
adt.into(),
);
- Ty::new_adt(self.ctx.interner, AdtDef::new(adt, self.ctx.interner), args)
+ Ty::new_adt(self.ctx.interner, adt, args)
}
TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args),
@@ -308,7 +311,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
tracing::debug!(?ty);
self.skip_resolved_segment();
- self.lower_ty_relative_path(ty, Some(resolution))
+ self.lower_ty_relative_path(ty, Some(resolution), infer_args)
}
fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) {
@@ -480,14 +483,19 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
// 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(_) | ValueNs::ConstId(_) => {
+ ValueNs::GenericParam(_) => {
prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const)
}
ValueNs::StaticId(_) => {
prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static)
}
- ValueNs::FunctionId(_) | ValueNs::StructId(_) | ValueNs::EnumVariantId(_) => {}
- ValueNs::LocalBinding(_) => {}
+ ValueNs::LocalBinding(_) => {
+ prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable)
+ }
+ ValueNs::FunctionId(_)
+ | ValueNs::StructId(_)
+ | ValueNs::EnumVariantId(_)
+ | ValueNs::ConstId(_) => {}
}
}
ResolveValueResult::Partial(resolution, _, _) => {
@@ -498,7 +506,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
}
#[tracing::instrument(skip(self), ret)]
- fn select_associated_type(&mut self, res: Option<TypeNs>) -> Ty<'db> {
+ 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);
@@ -516,7 +524,8 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
// 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(), false, None, true);
+ let substs =
+ self.substs_from_path_segment(associated_ty.into(), infer_args, None, true);
let substs = crate::next_solver::GenericArgs::new_from_iter(
interner,
@@ -715,12 +724,12 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
param: GenericParamDataRef<'_>,
arg: &GenericArg,
) -> crate::next_solver::GenericArg<'db> {
- match (param, arg) {
+ match (param, *arg) {
(GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => {
- self.ctx.ctx.lower_lifetime(*lifetime).into()
+ self.ctx.ctx.lower_lifetime(lifetime).into()
}
(GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => {
- self.ctx.ctx.lower_ty(*type_ref).into()
+ self.ctx.ctx.lower_ty(type_ref).into()
}
(GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => {
let GenericParamId::ConstParamId(const_id) = param_id else {
@@ -859,8 +868,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
&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);
+ let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args);
TraitRef::new_from_args(self.ctx.interner, resolved.into(), args)
}
@@ -868,8 +878,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
&mut self,
resolved: TraitId,
explicit_self_ty: Ty<'db>,
+ infer_args: bool,
) -> crate::next_solver::GenericArgs<'db> {
- self.substs_from_path_segment(resolved.into(), false, Some(explicit_self_ty), false)
+ self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false)
}
pub(super) fn assoc_type_bindings_from_type_bound<'c>(
@@ -1039,8 +1050,12 @@ fn check_generic_args_len<'db>(
}
let lifetime_args_len = def_generics.len_lifetimes_self();
- if provided_lifetimes_count == 0 && lifetime_args_len > 0 && !lowering_assoc_type_generics {
- // In generic associated types, we never allow inferring the lifetimes.
+ 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);
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 61d3091a0c..086abc9591 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -8,39 +8,42 @@ use arrayvec::ArrayVec;
use base_db::Crate;
use chalk_ir::{UniverseIndex, WithKind, cast::Cast};
use hir_def::{
- AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup,
- ModuleId, TraitId,
+ AdtId, AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup,
+ ModuleId, TraitId, TypeAliasId,
nameres::{DefMap, assoc::ImplItems, block_def_map, crate_def_map},
signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags},
};
use hir_expand::name::Name;
use intern::sym;
+use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
-use rustc_type_ir::inherent::{IntoKind, SliceLike, Ty as _};
+use rustc_type_ir::{
+ FloatTy, IntTy, UintTy,
+ inherent::{
+ AdtDef, BoundExistentialPredicates, GenericArgs as _, IntoKind, SliceLike, Ty as _,
+ },
+};
use smallvec::{SmallVec, smallvec};
use stdx::never;
use triomphe::Arc;
use crate::{
- AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData,
- Goal, InEnvironment, Interner, Mutability, Scalar, Substitution, TraitEnvironment, TraitRef,
- TraitRefExt, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause,
+ CanonicalVarKinds, DebruijnIndex, GenericArgData, InEnvironment, Interner, TraitEnvironment,
+ TyBuilder, VariableKind,
autoderef::{self, AutoderefKind},
db::HirDatabase,
- from_chalk_trait_id, from_foreign_def_id,
infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable},
lang_items::is_box,
next_solver::{
- self, DbInterner, SolverDefId,
+ Canonical, DbInterner, ErrorGuaranteed, GenericArgs, Goal, Predicate, Region, SolverDefId,
+ TraitRef, Ty, TyKind,
infer::{
DefineOpaqueTypes,
traits::{ObligationCause, PredicateObligation},
},
- mapping::{ChalkToNextSolver, NextSolverToChalk},
+ mapping::NextSolverToChalk,
obligation_ctxt::ObligationCtxt,
},
- primitive::{FloatTy, IntTy, UintTy},
- to_chalk_trait_id,
traits::next_trait_solve_canonical_in_ctxt,
utils::all_super_traits,
};
@@ -55,11 +58,15 @@ pub enum TyFingerprint {
Never,
Ref(Mutability),
RawPtr(Mutability),
- Scalar(Scalar),
+ Bool,
+ Char,
+ Int(IntTy),
+ Uint(UintTy),
+ Float(FloatTy),
// These can have user-defined impls:
Adt(hir_def::AdtId),
Dyn(TraitId),
- ForeignType(ForeignDefId),
+ ForeignType(TypeAliasId),
// These only exist for trait impls
Unit,
Unnameable,
@@ -71,140 +78,73 @@ impl TyFingerprint {
/// types can have inherent impls: if we have some `struct S`, we can have
/// an `impl S`, but not `impl &S`. Hence, this will return `None` for
/// reference types and such.
- pub fn for_inherent_impl(ty: &Ty) -> Option<TyFingerprint> {
- let fp = match ty.kind(Interner) {
+ pub fn for_inherent_impl<'db>(ty: Ty<'db>) -> Option<TyFingerprint> {
+ let fp = match ty.kind() {
TyKind::Str => TyFingerprint::Str,
TyKind::Never => TyFingerprint::Never,
TyKind::Slice(..) => TyFingerprint::Slice,
TyKind::Array(..) => TyFingerprint::Array,
- TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
- TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
- TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
- TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
- TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?,
+ TyKind::Bool => TyFingerprint::Bool,
+ TyKind::Char => TyFingerprint::Char,
+ TyKind::Int(int) => TyFingerprint::Int(int),
+ TyKind::Uint(int) => TyFingerprint::Uint(int),
+ TyKind::Float(float) => TyFingerprint::Float(float),
+ TyKind::Adt(adt_def, _) => TyFingerprint::Adt(adt_def.def_id().0),
+ TyKind::RawPtr(_, mutability) => TyFingerprint::RawPtr(mutability),
+ TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(alias_id.0),
+ TyKind::Dynamic(bounds, _) => {
+ bounds.principal_def_id().map(|trait_| TyFingerprint::Dyn(trait_.0))?
+ }
_ => return None,
};
Some(fp)
}
/// Creates a TyFingerprint for looking up a trait impl.
- pub fn for_trait_impl(ty: &Ty) -> Option<TyFingerprint> {
- let fp = match ty.kind(Interner) {
+ pub fn for_trait_impl<'db>(ty: Ty<'db>) -> Option<TyFingerprint> {
+ let fp = match ty.kind() {
TyKind::Str => TyFingerprint::Str,
TyKind::Never => TyFingerprint::Never,
TyKind::Slice(..) => TyFingerprint::Slice,
TyKind::Array(..) => TyFingerprint::Array,
- TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
- TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
- TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
- TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
- TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?,
- TyKind::Ref(mutability, _, _) => TyFingerprint::Ref(*mutability),
- TyKind::Tuple(_, subst) => {
- let first_ty = subst.interned().first().map(|arg| arg.assert_ty_ref(Interner));
+ TyKind::Bool => TyFingerprint::Bool,
+ TyKind::Char => TyFingerprint::Char,
+ TyKind::Int(int) => TyFingerprint::Int(int),
+ TyKind::Uint(int) => TyFingerprint::Uint(int),
+ TyKind::Float(float) => TyFingerprint::Float(float),
+ TyKind::Adt(adt_def, _) => TyFingerprint::Adt(adt_def.def_id().0),
+ TyKind::RawPtr(_, mutability) => TyFingerprint::RawPtr(mutability),
+ TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(alias_id.0),
+ TyKind::Dynamic(bounds, _) => {
+ bounds.principal_def_id().map(|trait_| TyFingerprint::Dyn(trait_.0))?
+ }
+ TyKind::Ref(_, _, mutability) => TyFingerprint::Ref(mutability),
+ TyKind::Tuple(subst) => {
+ let first_ty = subst.as_slice().first();
match first_ty {
- Some(ty) => return TyFingerprint::for_trait_impl(ty),
+ Some(ty) => return TyFingerprint::for_trait_impl(*ty),
None => TyFingerprint::Unit,
}
}
- TyKind::AssociatedType(_, _)
// FIXME(next-solver): Putting `Alias` here is *probably* incorrect, AFAIK it should return `None`. But this breaks
// flyimport, which uses an incorrect but fast method resolution algorithm. Therefore we put it here,
// because this function is only called by flyimport, and anyway we should get rid of `TyFingerprint`
// and switch to `rustc_type_ir`'s `SimplifiedType`.
- | TyKind::Alias(_)
- | TyKind::OpaqueType(_, _)
+ TyKind::Alias(..)
| TyKind::FnDef(_, _)
| TyKind::Closure(_, _)
| TyKind::Coroutine(..)
+ | TyKind::CoroutineClosure(..)
| TyKind::CoroutineWitness(..) => TyFingerprint::Unnameable,
- TyKind::Function(fn_ptr) => {
- TyFingerprint::Function(fn_ptr.substitution.0.len(Interner) as u32)
- }
- TyKind::Placeholder(_)
- | TyKind::BoundVar(_)
- | TyKind::InferenceVar(_, _)
- | TyKind::Error => return None,
- };
- Some(fp)
- }
-
- /// Creates a TyFingerprint for looking up a trait impl.
- pub fn for_trait_impl_ns<'db>(ty: &next_solver::Ty<'db>) -> Option<TyFingerprint> {
- use rustc_type_ir::TyKind;
- let fp = match (*ty).kind() {
- TyKind::Str => TyFingerprint::Str,
- TyKind::Never => TyFingerprint::Never,
- TyKind::Slice(..) => TyFingerprint::Slice,
- TyKind::Array(..) => TyFingerprint::Array,
- TyKind::Int(int) => TyFingerprint::Scalar(Scalar::Int(match int {
- rustc_type_ir::IntTy::Isize => IntTy::Isize,
- rustc_type_ir::IntTy::I8 => IntTy::I8,
- rustc_type_ir::IntTy::I16 => IntTy::I16,
- rustc_type_ir::IntTy::I32 => IntTy::I32,
- rustc_type_ir::IntTy::I64 => IntTy::I64,
- rustc_type_ir::IntTy::I128 => IntTy::I128,
- })),
- TyKind::Uint(uint) => TyFingerprint::Scalar(Scalar::Uint(match uint {
- rustc_type_ir::UintTy::Usize => UintTy::Usize,
- rustc_type_ir::UintTy::U8 => UintTy::U8,
- rustc_type_ir::UintTy::U16 => UintTy::U16,
- rustc_type_ir::UintTy::U32 => UintTy::U32,
- rustc_type_ir::UintTy::U64 => UintTy::U64,
- rustc_type_ir::UintTy::U128 => UintTy::U128,
- })),
- TyKind::Float(float) => TyFingerprint::Scalar(Scalar::Float(match float {
- rustc_type_ir::FloatTy::F16 => FloatTy::F16,
- rustc_type_ir::FloatTy::F32 => FloatTy::F32,
- rustc_type_ir::FloatTy::F64 => FloatTy::F64,
- rustc_type_ir::FloatTy::F128 => FloatTy::F128,
- })),
- TyKind::Bool => TyFingerprint::Scalar(Scalar::Bool),
- TyKind::Char => TyFingerprint::Scalar(Scalar::Char),
- TyKind::Adt(def, _) => TyFingerprint::Adt(def.inner().id),
- TyKind::RawPtr(.., mutability) => match mutability {
- rustc_ast_ir::Mutability::Mut => TyFingerprint::RawPtr(Mutability::Mut),
- rustc_ast_ir::Mutability::Not => TyFingerprint::RawPtr(Mutability::Not),
- },
- TyKind::Foreign(def) => TyFingerprint::ForeignType(crate::to_foreign_def_id(def.0)),
- TyKind::Dynamic(bounds, _) => {
- let trait_ref = bounds
- .as_slice()
- .iter()
- .map(|b| (*b).skip_binder())
- .filter_map(|b| match b {
- rustc_type_ir::ExistentialPredicate::Trait(t) => Some(t.def_id),
- _ => None,
- })
- .next()?;
- TyFingerprint::Dyn(trait_ref.0)
- }
- TyKind::Ref(_, _, mutability) => match mutability {
- rustc_ast_ir::Mutability::Mut => TyFingerprint::Ref(Mutability::Mut),
- rustc_ast_ir::Mutability::Not => TyFingerprint::Ref(Mutability::Not),
- },
- TyKind::Tuple(tys) => {
- let first_ty = tys.as_slice().iter().next();
- match first_ty {
- Some(ty) => return TyFingerprint::for_trait_impl_ns(ty),
- None => TyFingerprint::Unit,
- }
- }
- TyKind::FnDef(_, _)
- | TyKind::Closure(_, _)
- | TyKind::Coroutine(..)
- | TyKind::CoroutineWitness(..)
- | TyKind::Pat(..)
- | TyKind::CoroutineClosure(..) => TyFingerprint::Unnameable,
TyKind::FnPtr(sig, _) => {
- TyFingerprint::Function(sig.inputs().skip_binder().len() as u32)
+ TyFingerprint::Function(sig.skip_binder().inputs_and_output.inner().len() as u32)
}
- TyKind::Alias(..)
- | TyKind::Placeholder(_)
+ TyKind::Param(_)
| TyKind::Bound(..)
+ | TyKind::Placeholder(..)
| TyKind::Infer(_)
| TyKind::Error(_)
- | TyKind::Param(..)
+ | TyKind::Pat(..)
| TyKind::UnsafeBinder(..) => return None,
};
Some(fp)
@@ -212,25 +152,25 @@ impl TyFingerprint {
}
pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
- TyFingerprint::Scalar(Scalar::Int(IntTy::I8)),
- TyFingerprint::Scalar(Scalar::Int(IntTy::I16)),
- TyFingerprint::Scalar(Scalar::Int(IntTy::I32)),
- TyFingerprint::Scalar(Scalar::Int(IntTy::I64)),
- TyFingerprint::Scalar(Scalar::Int(IntTy::I128)),
- TyFingerprint::Scalar(Scalar::Int(IntTy::Isize)),
- TyFingerprint::Scalar(Scalar::Uint(UintTy::U8)),
- TyFingerprint::Scalar(Scalar::Uint(UintTy::U16)),
- TyFingerprint::Scalar(Scalar::Uint(UintTy::U32)),
- TyFingerprint::Scalar(Scalar::Uint(UintTy::U64)),
- TyFingerprint::Scalar(Scalar::Uint(UintTy::U128)),
- TyFingerprint::Scalar(Scalar::Uint(UintTy::Usize)),
+ TyFingerprint::Int(IntTy::I8),
+ TyFingerprint::Int(IntTy::I16),
+ TyFingerprint::Int(IntTy::I32),
+ TyFingerprint::Int(IntTy::I64),
+ TyFingerprint::Int(IntTy::I128),
+ TyFingerprint::Int(IntTy::Isize),
+ TyFingerprint::Uint(UintTy::U8),
+ TyFingerprint::Uint(UintTy::U16),
+ TyFingerprint::Uint(UintTy::U32),
+ TyFingerprint::Uint(UintTy::U64),
+ TyFingerprint::Uint(UintTy::U128),
+ TyFingerprint::Uint(UintTy::Usize),
];
pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 4] = [
- TyFingerprint::Scalar(Scalar::Float(FloatTy::F16)),
- TyFingerprint::Scalar(Scalar::Float(FloatTy::F32)),
- TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)),
- TyFingerprint::Scalar(Scalar::Float(FloatTy::F128)),
+ TyFingerprint::Float(FloatTy::F16),
+ TyFingerprint::Float(FloatTy::F32),
+ TyFingerprint::Float(FloatTy::F64),
+ TyFingerprint::Float(FloatTy::F128),
];
type TraitFpMap = FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Box<[ImplId]>>>;
@@ -300,9 +240,8 @@ impl TraitImpls {
Some(tr) => tr.skip_binder().def_id.0,
None => continue,
};
- let interner = DbInterner::new_with(db, None, None);
- let self_ty = db.impl_self_ty(impl_id).instantiate_identity().to_chalk(interner);
- let self_ty_fp = TyFingerprint::for_trait_impl(&self_ty);
+ let self_ty = db.impl_self_ty(impl_id);
+ let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.instantiate_identity());
map.entry(target_trait).or_default().entry(self_ty_fp).or_default().push(impl_id);
}
@@ -415,8 +354,8 @@ impl InherentImpls {
continue;
}
- let interner = DbInterner::new_with(db, None, None);
- let self_ty = &db.impl_self_ty(impl_id).instantiate_identity().to_chalk(interner);
+ let self_ty = db.impl_self_ty(impl_id);
+ let self_ty = self_ty.instantiate_identity();
match is_inherent_impl_coherent(db, def_map, impl_id, self_ty) {
true => {
@@ -440,7 +379,7 @@ impl InherentImpls {
}
}
- pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
+ pub fn for_self_ty<'db>(&self, self_ty: Ty<'db>) -> &[ImplId] {
match TyFingerprint::for_inherent_impl(self_ty) {
Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
None => &[],
@@ -476,9 +415,14 @@ pub(crate) fn incoherent_inherent_impl_crates(
res
}
-pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<SmallVec<[Crate; 2]>> {
- match ty.kind(Interner) {
- &TyKind::Adt(AdtId(def_id), _) => {
+pub fn def_crates<'db>(
+ db: &'db dyn HirDatabase,
+ ty: Ty<'db>,
+ cur_crate: Crate,
+) -> Option<SmallVec<[Crate; 2]>> {
+ match ty.kind() {
+ TyKind::Adt(adt_def, _) => {
+ let def_id = adt_def.def_id().0;
let rustc_has_incoherent_inherent_impls = match def_id {
hir_def::AdtId::StructId(id) => db
.struct_signature(id)
@@ -499,22 +443,22 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma
smallvec![def_id.module(db).krate()]
})
}
- &TyKind::Foreign(id) => {
- let alias = from_foreign_def_id(id);
+ TyKind::Foreign(alias) => {
+ let alias = alias.0;
Some(
if db
.type_alias_signature(alias)
.flags
.contains(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPL)
{
- db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(id))
+ db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(alias))
} else {
smallvec![alias.module(db).krate()]
},
)
}
- TyKind::Dyn(_) => {
- let trait_id = ty.dyn_trait()?;
+ TyKind::Dynamic(bounds, _) => {
+ let trait_id = bounds.principal_def_id()?.0;
Some(
if db
.trait_signature(trait_id)
@@ -530,11 +474,15 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma
// for primitives, there may be impls in various places (core and alloc
// mostly). We just check the whole crate graph for crates with impls
// (cached behind a query).
- TyKind::Scalar(_)
+ TyKind::Bool
+ | TyKind::Char
+ | TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
| TyKind::Str
| TyKind::Slice(_)
| TyKind::Array(..)
- | TyKind::Raw(..) => Some(db.incoherent_inherent_impl_crates(
+ | TyKind::RawPtr(..) => Some(db.incoherent_inherent_impl_crates(
cur_crate,
TyFingerprint::for_inherent_impl(ty).expect("fingerprint for primitive"),
)),
@@ -545,7 +493,7 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma
/// Look up the method with the given name.
pub(crate) fn lookup_method<'db>(
db: &'db dyn HirDatabase,
- ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
+ ty: &Canonical<'db, Ty<'db>>,
env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
@@ -626,23 +574,23 @@ pub struct ReceiverAdjustments {
}
impl ReceiverAdjustments {
- pub(crate) fn apply(
+ pub(crate) fn apply<'db>(
&self,
- table: &mut InferenceTable<'_>,
- mut ty: Ty,
- ) -> (Ty, Vec<Adjustment>) {
+ table: &mut InferenceTable<'db>,
+ mut ty: Ty<'db>,
+ ) -> (Ty<'db>, Vec<Adjustment<'db>>) {
let mut adjust = Vec::new();
- let mut autoderef = table.autoderef(ty.to_nextsolver(table.interner));
+ let mut autoderef = table.autoderef(ty);
autoderef.next();
for _ in 0..self.autoderefs {
match autoderef.next() {
None => {
never!("autoderef not possible for {:?}", ty);
- ty = TyKind::Error.intern(Interner);
+ ty = Ty::new_error(table.interner(), ErrorGuaranteed);
break;
}
Some((new_ty, _)) => {
- ty = new_ty.to_chalk(autoderef.table.interner);
+ ty = new_ty;
let mutbl = match self.autoref {
Some(AutorefOrPtrAdjustment::Autoref(m)) => Some(m),
Some(AutorefOrPtrAdjustment::ToConstPtr) => Some(Mutability::Not),
@@ -654,26 +602,26 @@ impl ReceiverAdjustments {
AutoderefKind::Overloaded => Some(OverloadedDeref(mutbl)),
AutoderefKind::Builtin => None,
}),
- target: ty.clone(),
+ target: ty,
});
}
}
}
if let Some(autoref) = &self.autoref {
- let lt = table.new_lifetime_var();
+ let lt = table.next_region_var();
match autoref {
AutorefOrPtrAdjustment::Autoref(m) => {
- let a = Adjustment::borrow(*m, ty, lt);
- ty = a.target.clone();
+ let a = Adjustment::borrow(table.interner(), *m, ty, lt);
+ ty = a.target;
adjust.push(a);
}
AutorefOrPtrAdjustment::ToConstPtr => {
- if let TyKind::Raw(Mutability::Mut, pointee) = ty.kind(Interner) {
+ if let TyKind::RawPtr(pointee, Mutability::Mut) = ty.kind() {
let a = Adjustment {
kind: Adjust::Pointer(PointerCast::MutToConstPointer),
- target: TyKind::Raw(Mutability::Not, pointee.clone()).intern(Interner),
+ target: Ty::new_ptr(table.interner(), pointee, Mutability::Not),
};
- ty = a.target.clone();
+ ty = a.target;
adjust.push(a);
} else {
never!("`ToConstPtr` target is not a raw mutable pointer");
@@ -683,23 +631,20 @@ impl ReceiverAdjustments {
}
if self.unsize_array {
ty = 'it: {
- if let TyKind::Ref(m, l, inner) = ty.kind(Interner)
- && let TyKind::Array(inner, _) = inner.kind(Interner)
+ if let TyKind::Ref(l, inner, m) = ty.kind()
+ && let TyKind::Array(inner, _) = inner.kind()
{
- break 'it TyKind::Ref(
- *m,
- l.clone(),
- TyKind::Slice(inner.clone()).intern(Interner),
- )
- .intern(Interner);
+ break 'it Ty::new_ref(
+ table.interner(),
+ l,
+ Ty::new_slice(table.interner(), inner),
+ m,
+ );
}
// FIXME: report diagnostic if array unsizing happens without indirection.
ty
};
- adjust.push(Adjustment {
- kind: Adjust::Pointer(PointerCast::Unsize),
- target: ty.clone(),
- });
+ adjust.push(Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target: ty });
}
(ty, adjust)
}
@@ -713,7 +658,7 @@ impl ReceiverAdjustments {
// lifetime problems, because we need to borrow temp `CrateImplDefs`.
// FIXME add a context type here?
pub(crate) fn iterate_method_candidates<'db, T>(
- ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
+ ty: &Canonical<'db, Ty<'db>>,
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
@@ -744,17 +689,18 @@ pub(crate) fn iterate_method_candidates<'db, T>(
}
pub fn lookup_impl_const<'db>(
- db: &'db dyn HirDatabase,
+ interner: DbInterner<'db>,
env: Arc<TraitEnvironment<'db>>,
const_id: ConstId,
- subs: Substitution,
-) -> (ConstId, Substitution) {
+ subs: GenericArgs<'db>,
+) -> (ConstId, GenericArgs<'db>) {
+ let db = interner.db;
+
let trait_id = match const_id.lookup(db).container {
ItemContainerId::TraitId(id) => id,
_ => return (const_id, subs),
};
- let substitution = Substitution::from_iter(Interner, subs.iter(Interner));
- let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution };
+ let trait_ref = TraitRef::new(interner, trait_id.into(), subs);
let const_signature = db.const_signature(const_id);
let name = match const_signature.name.as_ref() {
@@ -772,37 +718,30 @@ pub fn lookup_impl_const<'db>(
/// Checks if the self parameter of `Trait` method is the `dyn Trait` and we should
/// call the method using the vtable.
pub fn is_dyn_method<'db>(
- db: &'db dyn HirDatabase,
+ interner: DbInterner<'db>,
_env: Arc<TraitEnvironment<'db>>,
func: FunctionId,
- fn_subst: Substitution,
+ fn_subst: GenericArgs<'db>,
) -> Option<usize> {
+ let db = interner.db;
+
let ItemContainerId::TraitId(trait_id) = func.lookup(db).container else {
return None;
};
let trait_params = db.generic_params(trait_id.into()).len();
- let fn_params = fn_subst.len(Interner) - trait_params;
- let trait_ref = TraitRef {
- trait_id: to_chalk_trait_id(trait_id),
- substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)),
- };
- let self_ty = trait_ref.self_type_parameter(Interner);
- if let TyKind::Dyn(d) = self_ty.kind(Interner) {
+ let fn_params = fn_subst.len() - trait_params;
+ let trait_ref = TraitRef::new(
+ interner,
+ trait_id.into(),
+ GenericArgs::new_from_iter(interner, fn_subst.iter().take(trait_params)),
+ );
+ let self_ty = trait_ref.self_ty();
+ if let TyKind::Dynamic(d, _) = self_ty.kind() {
+ // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
+ // what the generics are, we are sure that the method is come from the vtable.
let is_my_trait_in_bounds = d
- .bounds
- .skip_binders()
- .as_slice(Interner)
- .iter()
- .map(|it| it.skip_binders())
- .flat_map(|it| match it {
- WhereClause::Implemented(tr) => {
- all_super_traits(db, from_chalk_trait_id(tr.trait_id))
- }
- _ => smallvec![],
- })
- // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
- // what the generics are, we are sure that the method is come from the vtable.
- .any(|x| x == trait_id);
+ .principal_def_id()
+ .is_some_and(|trait_| all_super_traits(db, trait_.0).contains(&trait_id));
if is_my_trait_in_bounds {
return Some(fn_params);
}
@@ -817,16 +756,19 @@ pub(crate) fn lookup_impl_method_query<'db>(
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
func: FunctionId,
- fn_subst: Substitution,
-) -> (FunctionId, Substitution) {
+ fn_subst: GenericArgs<'db>,
+) -> (FunctionId, GenericArgs<'db>) {
+ let interner = DbInterner::new_with(db, Some(env.krate), env.block);
+
let ItemContainerId::TraitId(trait_id) = func.lookup(db).container else {
return (func, fn_subst);
};
let trait_params = db.generic_params(trait_id.into()).len();
- let trait_ref = TraitRef {
- trait_id: to_chalk_trait_id(trait_id),
- substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)),
- };
+ let trait_ref = TraitRef::new(
+ interner,
+ trait_id.into(),
+ GenericArgs::new_from_iter(interner, fn_subst.iter().take(trait_params)),
+ );
let name = &db.function_signature(func).name;
let Some((impl_fn, impl_subst)) =
@@ -839,28 +781,28 @@ pub(crate) fn lookup_impl_method_query<'db>(
(
impl_fn,
- Substitution::from_iter(
- Interner,
- impl_subst.iter(Interner).chain(fn_subst.iter(Interner).skip(trait_params)),
+ GenericArgs::new_from_iter(
+ interner,
+ impl_subst.iter().chain(fn_subst.iter().skip(trait_params)),
),
)
}
fn lookup_impl_assoc_item_for_trait_ref<'db>(
- trait_ref: TraitRef,
+ trait_ref: TraitRef<'db>,
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
name: &Name,
-) -> Option<(AssocItemId, Substitution)> {
- let hir_trait_id = trait_ref.hir_trait_id();
- let self_ty = trait_ref.self_type_parameter(Interner);
- let self_ty_fp = TyFingerprint::for_trait_impl(&self_ty)?;
+) -> Option<(AssocItemId, GenericArgs<'db>)> {
+ let hir_trait_id = trait_ref.def_id.0;
+ let self_ty = trait_ref.self_ty();
+ let self_ty_fp = TyFingerprint::for_trait_impl(self_ty)?;
let impls = db.trait_impls_in_deps(env.krate);
let trait_module = hir_trait_id.module(db);
let type_module = match self_ty_fp {
TyFingerprint::Adt(adt_id) => Some(adt_id.module(db)),
- TyFingerprint::ForeignType(type_id) => Some(from_foreign_def_id(type_id).module(db)),
+ TyFingerprint::ForeignType(type_id) => Some(type_id.module(db)),
TyFingerprint::Dyn(trait_id) => Some(trait_id.module(db)),
_ => None,
};
@@ -888,84 +830,85 @@ fn lookup_impl_assoc_item_for_trait_ref<'db>(
Some((item, impl_subst))
}
-fn find_matching_impl(
+fn find_matching_impl<'db>(
mut impls: impl Iterator<Item = ImplId>,
- mut table: InferenceTable<'_>,
- actual_trait_ref: TraitRef,
-) -> Option<(&ImplItems, Substitution)> {
+ mut table: InferenceTable<'db>,
+ actual_trait_ref: TraitRef<'db>,
+) -> Option<(&'db ImplItems, GenericArgs<'db>)> {
let db = table.db;
impls.find_map(|impl_| {
table.run_in_snapshot(|table| {
- let impl_substs =
- TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build();
- let args: crate::next_solver::GenericArgs<'_> =
- impl_substs.to_nextsolver(table.interner);
+ let impl_substs = table.fresh_args_for_item(impl_.into());
let trait_ref = db
.impl_trait(impl_)
.expect("non-trait method in find_matching_impl")
- .instantiate(table.interner, args)
- .to_chalk(table.interner);
+ .instantiate(table.interner(), impl_substs);
- if !table.unify(&trait_ref, &actual_trait_ref) {
+ if !table.unify(trait_ref, actual_trait_ref) {
return None;
}
- let wcs = crate::chalk_db::convert_where_clauses(db, impl_.into(), &impl_substs)
- .into_iter()
- .map(|b| -> Goal { b.cast(Interner) });
- for goal in wcs {
- let goal = goal.to_nextsolver(table.interner);
- if table.try_obligation(goal).no_solution() {
- return None;
+ if let Some(predicates) =
+ db.generic_predicates_ns(impl_.into()).instantiate(table.interner(), impl_substs)
+ {
+ for predicate in predicates {
+ if table.try_obligation(predicate.0).no_solution() {
+ return None;
+ }
+ table.register_obligation(predicate.0);
}
- table.register_obligation(goal);
}
- Some((
- impl_.impl_items(db),
- table.resolve_completely::<_, crate::next_solver::GenericArgs<'_>>(impl_substs),
- ))
+ Some((impl_.impl_items(db), table.resolve_completely(impl_substs)))
})
})
}
-fn is_inherent_impl_coherent(
- db: &dyn HirDatabase,
+fn is_inherent_impl_coherent<'db>(
+ db: &'db dyn HirDatabase,
def_map: &DefMap,
impl_id: ImplId,
- self_ty: &Ty,
+ self_ty: Ty<'db>,
) -> bool {
- let self_ty = self_ty.kind(Interner);
+ let self_ty = self_ty.kind();
let impl_allowed = match self_ty {
- TyKind::Tuple(_, _)
+ TyKind::Tuple(_)
| TyKind::FnDef(_, _)
| TyKind::Array(_, _)
| TyKind::Never
- | TyKind::Raw(_, _)
+ | TyKind::RawPtr(_, _)
| TyKind::Ref(_, _, _)
| TyKind::Slice(_)
| TyKind::Str
- | TyKind::Scalar(_) => def_map.is_rustc_coherence_is_core(),
+ | TyKind::Bool
+ | TyKind::Char
+ | TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_) => def_map.is_rustc_coherence_is_core(),
- &TyKind::Adt(AdtId(adt), _) => adt.module(db).krate() == def_map.krate(),
- TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| {
- from_chalk_trait_id(trait_id).module(db).krate() == def_map.krate()
- }),
+ TyKind::Adt(adt_def, _) => adt_def.def_id().0.module(db).krate() == def_map.krate(),
+ TyKind::Dynamic(it, _) => it
+ .principal_def_id()
+ .is_some_and(|trait_id| trait_id.0.module(db).krate() == def_map.krate()),
_ => true,
};
impl_allowed || {
let rustc_has_incoherent_inherent_impls = match self_ty {
- TyKind::Tuple(_, _)
+ TyKind::Tuple(_)
| TyKind::FnDef(_, _)
| TyKind::Array(_, _)
| TyKind::Never
- | TyKind::Raw(_, _)
+ | TyKind::RawPtr(_, _)
| TyKind::Ref(_, _, _)
| TyKind::Slice(_)
| TyKind::Str
- | TyKind::Scalar(_) => true,
+ | TyKind::Bool
+ | TyKind::Char
+ | TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_) => true,
- &TyKind::Adt(AdtId(adt), _) => match adt {
+ TyKind::Adt(adt_def, _) => match adt_def.def_id().0 {
hir_def::AdtId::StructId(id) => db
.struct_signature(id)
.flags
@@ -979,8 +922,8 @@ fn is_inherent_impl_coherent(
.flags
.contains(EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
},
- TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| {
- db.trait_signature(from_chalk_trait_id(trait_id))
+ TyKind::Dynamic(it, _) => it.principal_def_id().is_some_and(|trait_id| {
+ db.trait_signature(trait_id.0)
.flags
.contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
}),
@@ -1012,8 +955,7 @@ fn is_inherent_impl_coherent(
/// - All of
/// - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type.
/// - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`)
-pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
- let substs = TyBuilder::placeholder_subst(db, impl_);
+pub fn check_orphan_rules<'db>(db: &'db dyn HirDatabase, impl_: ImplId) -> bool {
let Some(impl_trait) = db.impl_trait(impl_) else {
// not a trait impl
return true;
@@ -1022,24 +964,25 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
let local_crate = impl_.lookup(db).container.krate();
let is_local = |tgt_crate| tgt_crate == local_crate;
- let interner = DbInterner::new_with(db, None, None);
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- let trait_ref = impl_trait.instantiate(interner, args).to_chalk(interner);
- let trait_id = from_chalk_trait_id(trait_ref.trait_id);
+ let trait_ref = impl_trait.instantiate_identity();
+ let trait_id = trait_ref.def_id.0;
if is_local(trait_id.module(db).krate()) {
// trait to be implemented is local
return true;
}
- let unwrap_fundamental = |mut ty: Ty| {
+ let unwrap_fundamental = |mut ty: Ty<'db>| {
// Unwrap all layers of fundamental types with a loop.
loop {
- match ty.kind(Interner) {
- TyKind::Ref(_, _, referenced) => ty = referenced.clone(),
- &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => {
+ match ty.kind() {
+ TyKind::Ref(_, referenced, _) => ty = referenced,
+ TyKind::Adt(adt_def, subs) => {
+ let AdtId::StructId(s) = adt_def.def_id().0 else {
+ break ty;
+ };
let struct_signature = db.struct_signature(s);
if struct_signature.flags.contains(StructFlags::FUNDAMENTAL) {
- let next = subs.type_parameters(Interner).next();
+ let next = subs.types().next();
match next {
Some(it) => ty = it,
None => break ty,
@@ -1056,22 +999,20 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
// FIXME: param coverage
// - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`)
- let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| {
- match unwrap_fundamental(ty).kind(Interner) {
- &TyKind::Adt(AdtId(id), _) => is_local(id.module(db).krate()),
- TyKind::Error => true,
- TyKind::Dyn(it) => it
- .principal_id()
- .is_some_and(|trait_id| is_local(from_chalk_trait_id(trait_id).module(db).krate())),
- _ => false,
+ let is_not_orphan = trait_ref.args.types().any(|ty| match unwrap_fundamental(ty).kind() {
+ TyKind::Adt(adt_def, _) => is_local(adt_def.def_id().0.module(db).krate()),
+ TyKind::Error(_) => true,
+ TyKind::Dynamic(it, _) => {
+ it.principal_def_id().is_some_and(|trait_id| is_local(trait_id.0.module(db).krate()))
}
+ _ => false,
});
#[allow(clippy::let_and_return)]
is_not_orphan
}
pub fn iterate_path_candidates<'db>(
- ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
+ ty: &Canonical<'db, Ty<'db>>,
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
@@ -1093,7 +1034,7 @@ pub fn iterate_path_candidates<'db>(
}
pub fn iterate_method_candidates_dyn<'db>(
- ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
+ ty: &Canonical<'db, Ty<'db>>,
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
@@ -1132,7 +1073,7 @@ pub fn iterate_method_candidates_dyn<'db>(
// types*.
let mut table = InferenceTable::new(db, env);
- let ty = table.instantiate_canonical_ns(*ty);
+ let ty = table.instantiate_canonical(*ty);
let deref_chain = autoderef_method_receiver(&mut table, ty);
deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
@@ -1165,14 +1106,14 @@ pub fn iterate_method_candidates_dyn<'db>(
#[tracing::instrument(skip_all, fields(name = ?name))]
fn iterate_method_candidates_with_autoref<'db>(
table: &mut InferenceTable<'db>,
- receiver_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
+ receiver_ty: Canonical<'db, Ty<'db>>,
first_adjustment: ReceiverAdjustments,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: Option<&Name>,
callback: &mut dyn MethodCandidateCallback,
) -> ControlFlow<()> {
- let interner = table.interner;
+ let interner = table.interner();
let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| {
iterate_method_candidates_by_receiver(
@@ -1187,11 +1128,7 @@ fn iterate_method_candidates_with_autoref<'db>(
};
let mut maybe_reborrowed = first_adjustment.clone();
- if let rustc_type_ir::TyKind::Ref(_, _, m) = receiver_ty.value.kind() {
- let m = match m {
- rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut,
- rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not,
- };
+ if let TyKind::Ref(_, _, m) = receiver_ty.value.kind() {
// Prefer reborrow of references to move
maybe_reborrowed.autoref = Some(AutorefOrPtrAdjustment::Autoref(m));
maybe_reborrowed.autoderefs += 1;
@@ -1199,15 +1136,10 @@ fn iterate_method_candidates_with_autoref<'db>(
iterate_method_candidates_by_receiver(receiver_ty, maybe_reborrowed)?;
- let refed = next_solver::Canonical {
+ let refed = Canonical {
max_universe: receiver_ty.max_universe,
variables: receiver_ty.variables,
- value: next_solver::Ty::new_ref(
- interner,
- next_solver::Region::error(interner),
- receiver_ty.value,
- rustc_ast_ir::Mutability::Not,
- ),
+ value: Ty::new_ref(interner, Region::error(interner), receiver_ty.value, Mutability::Not),
};
iterate_method_candidates_by_receiver(
@@ -1215,15 +1147,10 @@ fn iterate_method_candidates_with_autoref<'db>(
first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)),
)?;
- let ref_muted = next_solver::Canonical {
+ let ref_muted = Canonical {
max_universe: receiver_ty.max_universe,
variables: receiver_ty.variables,
- value: next_solver::Ty::new_ref(
- interner,
- next_solver::Region::error(interner),
- receiver_ty.value,
- rustc_ast_ir::Mutability::Mut,
- ),
+ value: Ty::new_ref(interner, Region::error(interner), receiver_ty.value, Mutability::Mut),
};
iterate_method_candidates_by_receiver(
@@ -1231,12 +1158,10 @@ fn iterate_method_candidates_with_autoref<'db>(
first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)),
)?;
- if let rustc_type_ir::TyKind::RawPtr(ty, rustc_ast_ir::Mutability::Mut) =
- receiver_ty.value.kind()
- {
+ if let TyKind::RawPtr(ty, Mutability::Mut) = receiver_ty.value.kind() {
let const_ptr_ty = rustc_type_ir::Canonical {
max_universe: rustc_type_ir::UniverseIndex::ZERO,
- value: next_solver::Ty::new_ptr(interner, ty, rustc_ast_ir::Mutability::Not),
+ value: Ty::new_ptr(interner, ty, Mutability::Not),
variables: receiver_ty.variables,
};
iterate_method_candidates_by_receiver(
@@ -1290,30 +1215,27 @@ where
#[tracing::instrument(skip_all, fields(name = ?name))]
fn iterate_method_candidates_by_receiver<'db>(
table: &mut InferenceTable<'db>,
- receiver_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
+ receiver_ty: Canonical<'db, Ty<'db>>,
receiver_adjustments: ReceiverAdjustments,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: Option<&Name>,
callback: &mut dyn MethodCandidateCallback,
) -> ControlFlow<()> {
- let interner = table.interner;
- let receiver_ty = table.instantiate_canonical_ns(receiver_ty);
- let receiver_ty: crate::Ty = receiver_ty.to_chalk(interner);
+ let receiver_ty = table.instantiate_canonical(receiver_ty);
// We're looking for methods with *receiver* type receiver_ty. These could
// be found in any of the derefs of receiver_ty, so we have to go through
// that, including raw derefs.
table.run_in_snapshot(|table| {
- let mut autoderef =
- autoderef::Autoderef::new_no_tracking(table, receiver_ty.to_nextsolver(interner))
- .include_raw_pointers()
- .use_receiver_trait();
+ let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty)
+ .include_raw_pointers()
+ .use_receiver_trait();
while let Some((self_ty, _)) = autoderef.next() {
iterate_inherent_methods(
- &self_ty.to_chalk(interner),
+ self_ty,
autoderef.table,
name,
- Some(&receiver_ty),
+ Some(receiver_ty),
Some(receiver_adjustments.clone()),
visible_from_module,
LookupMode::MethodCall,
@@ -1325,23 +1247,21 @@ fn iterate_method_candidates_by_receiver<'db>(
ControlFlow::Continue(())
})?;
table.run_in_snapshot(|table| {
- let mut autoderef =
- autoderef::Autoderef::new_no_tracking(table, receiver_ty.to_nextsolver(interner))
- .include_raw_pointers()
- .use_receiver_trait();
+ let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty)
+ .include_raw_pointers()
+ .use_receiver_trait();
while let Some((self_ty, _)) = autoderef.next() {
- if matches!(self_ty.kind(), crate::next_solver::TyKind::Infer(rustc_type_ir::TyVar(_)))
- {
+ if matches!(self_ty.kind(), TyKind::Infer(rustc_type_ir::TyVar(_))) {
// don't try to resolve methods on unknown types
return ControlFlow::Continue(());
}
iterate_trait_method_candidates(
- &self_ty.to_chalk(interner),
+ self_ty,
autoderef.table,
traits_in_scope,
name,
- Some(&receiver_ty),
+ Some(receiver_ty),
Some(receiver_adjustments.clone()),
LookupMode::MethodCall,
&mut |adjustments, item, is_visible| {
@@ -1355,7 +1275,7 @@ fn iterate_method_candidates_by_receiver<'db>(
#[tracing::instrument(skip_all, fields(name = ?name))]
fn iterate_method_candidates_for_self_ty<'db>(
- self_ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
+ self_ty: &Canonical<'db, Ty<'db>>,
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
@@ -1364,9 +1284,9 @@ fn iterate_method_candidates_for_self_ty<'db>(
callback: &mut dyn MethodCandidateCallback,
) -> ControlFlow<()> {
let mut table = InferenceTable::new(db, env);
- let self_ty = table.instantiate_canonical_ns(*self_ty).to_chalk(table.interner);
+ let self_ty = table.instantiate_canonical(*self_ty);
iterate_inherent_methods(
- &self_ty,
+ self_ty,
&mut table,
name,
None,
@@ -1378,7 +1298,7 @@ fn iterate_method_candidates_for_self_ty<'db>(
},
)?;
iterate_trait_method_candidates(
- &self_ty,
+ self_ty,
&mut table,
traits_in_scope,
name,
@@ -1392,19 +1312,19 @@ fn iterate_method_candidates_for_self_ty<'db>(
}
#[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))]
-fn iterate_trait_method_candidates(
- self_ty: &Ty,
- table: &mut InferenceTable<'_>,
+fn iterate_trait_method_candidates<'db>(
+ self_ty: Ty<'db>,
+ table: &mut InferenceTable<'db>,
traits_in_scope: &FxHashSet<TraitId>,
name: Option<&Name>,
- receiver_ty: Option<&Ty>,
+ receiver_ty: Option<Ty<'db>>,
receiver_adjustments: Option<ReceiverAdjustments>,
mode: LookupMode,
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
) -> ControlFlow<()> {
let db = table.db;
- let canonical_self_ty = table.canonicalize(self_ty.clone().to_nextsolver(table.interner));
+ let canonical_self_ty = table.canonicalize(self_ty);
let krate = table.trait_env.krate;
'traits: for &t in traits_in_scope {
@@ -1416,7 +1336,7 @@ fn iterate_trait_method_candidates(
// This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for
// arrays.
if data.flags.contains(TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH)
- && matches!(self_ty.kind(Interner), TyKind::Array(..))
+ && matches!(self_ty.kind(), TyKind::Array(..))
{
// FIXME: this should really be using the edition of the method name's span, in case it
// comes from a macro
@@ -1426,9 +1346,9 @@ fn iterate_trait_method_candidates(
}
if data.flags.contains(TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH)
&& matches!(
- self_ty.kind(Interner), TyKind::Adt(AdtId(def), subst)
- if is_box(table.db, *def)
- && matches!(subst.at(Interner, 0).assert_ty_ref(Interner).kind(Interner), TyKind::Slice(..))
+ self_ty.kind(), TyKind::Adt(adt_def, subst)
+ if is_box(table.db, adt_def.def_id().0)
+ && matches!(subst.type_at(0).kind(), TyKind::Slice(..))
)
{
// FIXME: this should really be using the edition of the method name's span, in case it
@@ -1472,11 +1392,11 @@ fn iterate_trait_method_candidates(
}
#[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))]
-fn iterate_inherent_methods(
- self_ty: &Ty,
- table: &mut InferenceTable<'_>,
+fn iterate_inherent_methods<'db>(
+ self_ty: Ty<'db>,
+ table: &mut InferenceTable<'db>,
name: Option<&Name>,
- receiver_ty: Option<&Ty>,
+ receiver_ty: Option<Ty<'db>>,
receiver_adjustments: Option<ReceiverAdjustments>,
visible_from_module: VisibleFromModule,
mode: LookupMode,
@@ -1489,11 +1409,11 @@ fn iterate_inherent_methods(
// its super traits are considered inherent methods. This matters because these methods have
// higher priority than the other traits' methods, which would be considered in
// `iterate_trait_method_candidates()` only after this function.
- match self_ty.kind(Interner) {
- TyKind::Placeholder(_) => {
+ match self_ty.kind() {
+ TyKind::Param(_) => {
let env = table.trait_env.clone();
let traits = env
- .traits_in_scope_from_clauses(self_ty.clone())
+ .traits_in_scope_from_clauses(self_ty.to_chalk(table.interner()))
.flat_map(|t| all_super_traits(db, t));
iterate_inherent_trait_methods(
self_ty,
@@ -1506,9 +1426,9 @@ fn iterate_inherent_methods(
mode,
)?;
}
- TyKind::Dyn(_) => {
- if let Some(principal_trait) = self_ty.dyn_trait() {
- let traits = all_super_traits(db, principal_trait);
+ TyKind::Dynamic(bounds, _) => {
+ if let Some(principal_trait) = bounds.principal_def_id() {
+ let traits = all_super_traits(db, principal_trait.0);
iterate_inherent_trait_methods(
self_ty,
table,
@@ -1568,11 +1488,11 @@ fn iterate_inherent_methods(
return ControlFlow::Continue(());
#[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))]
- fn iterate_inherent_trait_methods(
- self_ty: &Ty,
- table: &mut InferenceTable<'_>,
+ fn iterate_inherent_trait_methods<'db>(
+ self_ty: Ty<'db>,
+ table: &mut InferenceTable<'db>,
name: Option<&Name>,
- receiver_ty: Option<&Ty>,
+ receiver_ty: Option<Ty<'db>>,
receiver_adjustments: Option<ReceiverAdjustments>,
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
traits: impl Iterator<Item = TraitId>,
@@ -1603,12 +1523,12 @@ fn iterate_inherent_methods(
}
#[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))]
- fn impls_for_self_ty(
+ fn impls_for_self_ty<'db>(
impls: &InherentImpls,
- self_ty: &Ty,
- table: &mut InferenceTable<'_>,
+ self_ty: Ty<'db>,
+ table: &mut InferenceTable<'db>,
name: Option<&Name>,
- receiver_ty: Option<&Ty>,
+ receiver_ty: Option<Ty<'db>>,
receiver_adjustments: Option<ReceiverAdjustments>,
visible_from_module: Option<ModuleId>,
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
@@ -1639,10 +1559,10 @@ fn iterate_inherent_methods(
/// Returns the receiver type for the index trait call.
pub(crate) fn resolve_indexing_op<'db>(
table: &mut InferenceTable<'db>,
- ty: next_solver::Canonical<'db, next_solver::Ty<'db>>,
+ ty: Canonical<'db, Ty<'db>>,
index_trait: TraitId,
) -> Option<ReceiverAdjustments> {
- let ty = table.instantiate_canonical_ns(ty);
+ let ty = table.instantiate_canonical(ty);
let deref_chain = autoderef_method_receiver(table, ty);
for (ty, adj) in deref_chain {
let goal = generic_implements_goal_ns(table, index_trait, ty);
@@ -1670,10 +1590,10 @@ enum IsValidCandidate {
}
#[tracing::instrument(skip_all, fields(name))]
-fn is_valid_impl_method_candidate(
- table: &mut InferenceTable<'_>,
- self_ty: &Ty,
- receiver_ty: Option<&Ty>,
+fn is_valid_impl_method_candidate<'db>(
+ table: &mut InferenceTable<'db>,
+ self_ty: Ty<'db>,
+ receiver_ty: Option<Ty<'db>>,
visible_from_module: Option<ModuleId>,
name: Option<&Name>,
impl_id: ImplId,
@@ -1705,9 +1625,8 @@ fn is_valid_impl_method_candidate(
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(DbInterner::conjure())
- .to_chalk(DbInterner::conjure());
- table.unify(&expected_self_ty, self_ty)
+ .build(table.interner());
+ table.unify(expected_self_ty, self_ty)
});
if !self_ty_matches {
cov_mark::hit!(const_candidate_self_type_mismatch);
@@ -1721,13 +1640,13 @@ fn is_valid_impl_method_candidate(
/// Checks whether a given `AssocItemId` is applicable for `receiver_ty`.
#[tracing::instrument(skip_all, fields(name))]
-fn is_valid_trait_method_candidate(
- table: &mut InferenceTable<'_>,
+fn is_valid_trait_method_candidate<'db>(
+ table: &mut InferenceTable<'db>,
trait_id: TraitId,
name: Option<&Name>,
- receiver_ty: Option<&Ty>,
+ receiver_ty: Option<Ty<'db>>,
item: AssocItemId,
- self_ty: &Ty,
+ self_ty: Ty<'db>,
mode: LookupMode,
) -> IsValidCandidate {
let db = table.db;
@@ -1738,27 +1657,20 @@ fn is_valid_trait_method_candidate(
check_that!(name.is_none_or(|n| n == &data.name));
table.run_in_snapshot(|table| {
- let impl_subst = TyBuilder::subst_for_def(db, trait_id, None)
- .fill_with_inference_vars(table)
- .build();
- let expect_self_ty = impl_subst.at(Interner, 0).assert_ty_ref(Interner).clone();
+ let impl_subst = table.fresh_args_for_item(trait_id.into());
+ let expect_self_ty = impl_subst.type_at(0);
- check_that!(table.unify(&expect_self_ty, self_ty));
+ check_that!(table.unify(expect_self_ty, self_ty));
if let Some(receiver_ty) = receiver_ty {
check_that!(data.has_self_param());
- let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst))
- .fill_with_inference_vars(table)
- .build();
+ let args = table.fill_rest_fresh_args(fn_id.into(), impl_subst);
- let args: crate::next_solver::GenericArgs<'_> =
- fn_subst.to_nextsolver(table.interner);
let sig = db.callable_item_signature(fn_id.into());
let expected_receiver = sig
.map_bound(|s| s.skip_binder().inputs_and_output.as_slice()[0])
- .instantiate(table.interner, args)
- .to_chalk(table.interner);
+ .instantiate(table.interner(), args);
// FIXME: Clean up this mess with some context struct like rustc's `ProbeContext`
let variance = match mode {
@@ -1767,16 +1679,8 @@ fn is_valid_trait_method_candidate(
};
let res = table
.infer_ctxt
- .at(
- &next_solver::infer::traits::ObligationCause::dummy(),
- table.trait_env.env,
- )
- .relate(
- DefineOpaqueTypes::No,
- expected_receiver.to_nextsolver(table.interner),
- variance,
- receiver_ty.to_nextsolver(table.interner),
- );
+ .at(&ObligationCause::dummy(), table.trait_env.env)
+ .relate(DefineOpaqueTypes::No, expected_receiver, variance, receiver_ty);
let Ok(infer_ok) = res else {
return IsValidCandidate::No;
};
@@ -1788,7 +1692,7 @@ fn is_valid_trait_method_candidate(
check_that!(ctxt.select_where_possible().is_empty());
}
- check_that!(table.unify(receiver_ty, &expected_receiver));
+ check_that!(table.unify(receiver_ty, expected_receiver));
}
IsValidCandidate::Yes
@@ -1805,13 +1709,13 @@ fn is_valid_trait_method_candidate(
}
#[tracing::instrument(skip_all, fields(name))]
-fn is_valid_impl_fn_candidate(
- table: &mut InferenceTable<'_>,
+fn is_valid_impl_fn_candidate<'db>(
+ table: &mut InferenceTable<'db>,
impl_id: ImplId,
fn_id: FunctionId,
name: Option<&Name>,
- receiver_ty: Option<&Ty>,
- self_ty: &Ty,
+ receiver_ty: Option<Ty<'db>>,
+ self_ty: Ty<'db>,
visible_from_module: Option<ModuleId>,
item_name: &Name,
) -> IsValidCandidate {
@@ -1829,34 +1733,28 @@ fn is_valid_impl_fn_candidate(
table.run_in_snapshot(|table| {
let _p = tracing::info_span!("subst_for_def").entered();
let impl_subst = table.infer_ctxt.fresh_args_for_item(impl_id.into());
- let expect_self_ty = db
- .impl_self_ty(impl_id)
- .instantiate(table.interner, &impl_subst)
- .to_chalk(table.interner);
+ let expect_self_ty = db.impl_self_ty(impl_id).instantiate(table.interner(), &impl_subst);
- check_that!(table.unify(&expect_self_ty, self_ty));
+ check_that!(table.unify(expect_self_ty, self_ty));
if let Some(receiver_ty) = receiver_ty {
let _p = tracing::info_span!("check_receiver_ty").entered();
check_that!(data.has_self_param());
- let fn_subst: crate::Substitution =
- table.infer_ctxt.fresh_args_for_item(fn_id.into()).to_chalk(table.interner);
+ let args = table.infer_ctxt.fresh_args_for_item(fn_id.into());
- let args: crate::next_solver::GenericArgs<'_> = fn_subst.to_nextsolver(table.interner);
let sig = db.callable_item_signature(fn_id.into());
let expected_receiver = sig
.map_bound(|s| s.skip_binder().inputs_and_output.as_slice()[0])
- .instantiate(table.interner, args)
- .to_chalk(table.interner);
+ .instantiate(table.interner(), args);
- check_that!(table.unify(receiver_ty, &expected_receiver));
+ check_that!(table.unify(receiver_ty, expected_receiver));
}
// 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 Some(predicates) = predicates.instantiate(table.interner, impl_subst) else {
+ let Some(predicates) = predicates.instantiate(table.interner(), impl_subst) else {
return IsValidCandidate::Yes;
};
@@ -1864,7 +1762,7 @@ fn is_valid_impl_fn_candidate(
ctxt.register_obligations(predicates.into_iter().map(|p| {
PredicateObligation::new(
- table.interner,
+ table.interner(),
ObligationCause::new(),
table.trait_env.env,
p.0,
@@ -1880,7 +1778,7 @@ fn is_valid_impl_fn_candidate(
}
pub fn implements_trait_unique<'db>(
- ty: &Canonical<Ty>,
+ ty: &crate::Canonical<crate::Ty>,
db: &'db dyn HirDatabase,
env: &TraitEnvironment<'db>,
trait_: TraitId,
@@ -1896,8 +1794,8 @@ fn generic_implements_goal<'db>(
db: &'db dyn HirDatabase,
env: &TraitEnvironment<'db>,
trait_: TraitId,
- self_ty: &Canonical<Ty>,
-) -> Canonical<InEnvironment<super::DomainGoal>> {
+ self_ty: &crate::Canonical<crate::Ty>,
+) -> crate::Canonical<crate::InEnvironment<crate::DomainGoal>> {
let binders = self_ty.binders.interned();
let trait_ref = TyBuilder::trait_ref(db, trait_)
.push(self_ty.value.clone())
@@ -1920,7 +1818,7 @@ fn generic_implements_goal<'db>(
&env.env.to_chalk(DbInterner::new_with(db, Some(env.krate), env.block)),
obligation,
);
- Canonical { binders, value }
+ crate::Canonical { binders, value }
}
/// This creates Substs for a trait with the given Self type and type variables
@@ -1929,23 +1827,23 @@ fn generic_implements_goal<'db>(
fn generic_implements_goal_ns<'db>(
table: &mut InferenceTable<'db>,
trait_: TraitId,
- self_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
-) -> next_solver::Canonical<'db, next_solver::Goal<'db, crate::next_solver::Predicate<'db>>> {
+ self_ty: Canonical<'db, Ty<'db>>,
+) -> Canonical<'db, Goal<'db, Predicate<'db>>> {
let args = table.infer_ctxt.fresh_args_for_item(SolverDefId::TraitId(trait_));
- let self_ty = table.instantiate_canonical_ns(self_ty);
+ let self_ty = table.instantiate_canonical(self_ty);
let trait_ref =
rustc_type_ir::TraitRef::new_from_args(table.infer_ctxt.interner, trait_.into(), args)
.with_replaced_self_ty(table.infer_ctxt.interner, self_ty);
- let goal = next_solver::Goal::new(table.infer_ctxt.interner, table.trait_env.env, trait_ref);
+ let goal = Goal::new(table.infer_ctxt.interner, table.trait_env.env, trait_ref);
table.canonicalize(goal)
}
fn autoderef_method_receiver<'db>(
table: &mut InferenceTable<'db>,
- ty: next_solver::Ty<'db>,
-) -> Vec<(next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> {
- let interner = table.interner;
+ ty: Ty<'db>,
+) -> Vec<(Canonical<'db, Ty<'db>>, ReceiverAdjustments)> {
+ let interner = table.interner();
let mut deref_chain = Vec::new();
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty).use_receiver_trait();
while let Some((ty, derefs)) = autoderef.next() {
@@ -1958,9 +1856,9 @@ fn autoderef_method_receiver<'db>(
if let Some((rustc_type_ir::Array(parameters, _), variables, max_universe, adj)) =
deref_chain.last().map(|d| (d.0.value.kind(), d.0.variables, d.0.max_universe, d.1.clone()))
{
- let unsized_ty = next_solver::Ty::new_slice(interner, parameters);
+ let unsized_ty = Ty::new_slice(interner, parameters);
deref_chain.push((
- next_solver::Canonical { max_universe, value: unsized_ty, variables },
+ Canonical { max_universe, value: unsized_ty, variables },
ReceiverAdjustments { unsize_array: true, ..adj.clone() },
));
}
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index 6465099dff..a05cc2a02b 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -708,10 +708,10 @@ impl BorrowKind {
}
}
- fn from_chalk(m: Mutability) -> Self {
+ fn from_rustc(m: rustc_ast_ir::Mutability) -> Self {
match m {
- Mutability::Not => BorrowKind::Shared,
- Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
+ rustc_ast_ir::Mutability::Not => BorrowKind::Shared,
+ rustc_ast_ir::Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
}
}
}
diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs
index 2c09fb9a89..08b1e03726 100644
--- a/crates/hir-ty/src/mir/borrowck.rs
+++ b/crates/hir-ty/src/mir/borrowck.rs
@@ -11,6 +11,8 @@ use rustc_hash::FxHashMap;
use stdx::never;
use triomphe::Arc;
+use crate::next_solver::DbInterner;
+use crate::next_solver::mapping::{ChalkToNextSolver, NextSolverToChalk};
use crate::{
ClosureId, Interner, Substitution, Ty, TyExt, TypeFlags,
db::{HirDatabase, InternedClosure},
@@ -61,16 +63,16 @@ pub struct BorrowckResult {
pub borrow_regions: Vec<BorrowRegion>,
}
-fn all_mir_bodies(
- db: &dyn HirDatabase,
+fn all_mir_bodies<'db>(
+ db: &'db dyn HirDatabase,
def: DefWithBodyId,
mut cb: impl FnMut(Arc<MirBody>),
-) -> Result<(), MirLowerError> {
- fn for_closure(
- db: &dyn HirDatabase,
+) -> Result<(), MirLowerError<'db>> {
+ fn for_closure<'db>(
+ db: &'db dyn HirDatabase,
c: ClosureId,
cb: &mut impl FnMut(Arc<MirBody>),
- ) -> Result<(), MirLowerError> {
+ ) -> Result<(), MirLowerError<'db>> {
match db.mir_body_for_closure(c.into()) {
Ok(body) => {
cb(body.clone());
@@ -88,10 +90,10 @@ fn all_mir_bodies(
}
}
-pub fn borrowck_query(
- db: &dyn HirDatabase,
+pub fn borrowck_query<'db>(
+ db: &'db dyn HirDatabase,
def: DefWithBodyId,
-) -> Result<Arc<[BorrowckResult]>, MirLowerError> {
+) -> Result<Arc<[BorrowckResult]>, MirLowerError<'db>> {
let _p = tracing::info_span!("borrowck_query").entered();
let mut res = vec![];
all_mir_bodies(db, def, |body| {
@@ -112,14 +114,17 @@ fn make_fetch_closure_field(
|c: ClosureId, subst: &Substitution, f: usize| {
let InternedClosure(def, _) = db.lookup_intern_closure(c.into());
let infer = db.infer(def);
- let (captures, _) = infer.closure_info(&c);
+ let (captures, _) = infer.closure_info(c.into());
let parent_subst = ClosureSubst(subst).parent_subst(db);
+ let interner = DbInterner::new_with(db, None, None);
+ let parent_subst: crate::next_solver::GenericArgs<'_> =
+ parent_subst.to_nextsolver(interner);
captures
.get(f)
.expect("broken closure field")
.ty
- .clone()
- .substitute(Interner, &parent_subst)
+ .instantiate(interner, parent_subst)
+ .to_chalk(interner)
}
}
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index fa63baa5d2..e46490e526 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -32,6 +32,7 @@ use stdx::never;
use syntax::{SyntaxNodePtr, TextRange};
use triomphe::Arc;
+use crate::next_solver::mapping::NextSolverToChalk;
use crate::{
AliasTy, CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, Interner,
MemoryMap, Substitution, ToChalk, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind,
@@ -102,13 +103,13 @@ impl<'db> VTableMap<'db> {
id
}
- pub(crate) fn ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>> {
+ pub(crate) fn ty(&self, id: usize) -> Result<'db, crate::next_solver::Ty<'db>> {
id.checked_sub(VTableMap::OFFSET)
.and_then(|id| self.id_to_ty.get(id).copied())
.ok_or(MirEvalError::InvalidVTableId(id))
}
- fn ty_of_bytes(&self, bytes: &[u8]) -> Result<crate::next_solver::Ty<'db>> {
+ fn ty_of_bytes(&self, bytes: &[u8]) -> Result<'db, crate::next_solver::Ty<'db>> {
let id = from_bytes!(usize, bytes);
self.ty(id)
}
@@ -134,14 +135,14 @@ impl TlsData {
self.keys.len() - 1
}
- fn get_key(&mut self, key: usize) -> Result<u128> {
+ fn get_key(&mut self, key: usize) -> Result<'static, u128> {
let r = self.keys.get(key).ok_or_else(|| {
MirEvalError::UndefinedBehavior(format!("Getting invalid tls key {key}"))
})?;
Ok(*r)
}
- fn set_key(&mut self, key: usize, value: u128) -> Result<()> {
+ fn set_key(&mut self, key: usize, value: u128) -> Result<'static, ()> {
let r = self.keys.get_mut(key).ok_or_else(|| {
MirEvalError::UndefinedBehavior(format!("Setting invalid tls key {key}"))
})?;
@@ -202,6 +203,7 @@ pub struct Evaluator<'a> {
stack_depth_limit: usize,
/// Maximum count of bytes that heap and stack can grow
memory_limit: usize,
+ interner: DbInterner<'a>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -230,15 +232,19 @@ impl Interval {
Self { addr, size }
}
- fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> {
+ fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<'db, &'a [u8]> {
memory.read_memory(self.addr, self.size)
}
- fn write_from_bytes(&self, memory: &mut Evaluator<'_>, bytes: &[u8]) -> Result<()> {
+ fn write_from_bytes<'db>(&self, memory: &mut Evaluator<'db>, bytes: &[u8]) -> Result<'db, ()> {
memory.write_memory(self.addr, bytes)
}
- fn write_from_interval(&self, memory: &mut Evaluator<'_>, interval: Interval) -> Result<()> {
+ fn write_from_interval<'db>(
+ &self,
+ memory: &mut Evaluator<'db>,
+ interval: Interval,
+ ) -> Result<'db, ()> {
memory.copy_from_interval(self.addr, interval)
}
@@ -248,16 +254,16 @@ impl Interval {
}
impl IntervalAndTy {
- fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> {
+ fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<'db, &'a [u8]> {
memory.read_memory(self.interval.addr, self.interval.size)
}
- fn new(
+ fn new<'db>(
addr: Address,
ty: Ty,
- evaluator: &Evaluator<'_>,
+ evaluator: &Evaluator<'db>,
locals: &Locals,
- ) -> Result<IntervalAndTy> {
+ ) -> Result<'db, IntervalAndTy> {
let size = evaluator.size_of_sized(&ty, locals, "type of interval")?;
Ok(IntervalAndTy { interval: Interval { addr, size }, ty })
}
@@ -275,7 +281,7 @@ impl From<Interval> for IntervalOrOwned {
}
impl IntervalOrOwned {
- fn get<'a, 'db>(&'a self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> {
+ fn get<'a, 'db>(&'a self, memory: &'a Evaluator<'db>) -> Result<'db, &'a [u8]> {
Ok(match self {
IntervalOrOwned::Owned(o) => o,
IntervalOrOwned::Borrowed(b) => b.get(memory)?,
@@ -295,7 +301,7 @@ const HEAP_OFFSET: usize = 1 << 29;
impl Address {
#[allow(clippy::double_parens)]
- fn from_bytes(it: &[u8]) -> Result<Self> {
+ fn from_bytes<'db>(it: &[u8]) -> Result<'db, Self> {
Ok(Address::from_usize(from_bytes!(usize, it)))
}
@@ -335,8 +341,8 @@ impl Address {
}
#[derive(Clone, PartialEq, Eq)]
-pub enum MirEvalError {
- ConstEvalError(String, Box<ConstEvalError>),
+pub enum MirEvalError<'db> {
+ ConstEvalError(String, Box<ConstEvalError<'db>>),
LayoutError(LayoutError, Ty),
TargetDataLayoutNotAvailable(TargetLoadError),
/// Means that code had undefined behavior. We don't try to actively detect UB, but if it was detected
@@ -344,12 +350,15 @@ pub enum MirEvalError {
UndefinedBehavior(String),
Panic(String),
// FIXME: This should be folded into ConstEvalError?
- MirLowerError(FunctionId, MirLowerError),
- MirLowerErrorForClosure(ClosureId, MirLowerError),
+ MirLowerError(FunctionId, MirLowerError<'db>),
+ MirLowerErrorForClosure(ClosureId, MirLowerError<'db>),
TypeIsUnsized(Ty, &'static str),
NotSupported(String),
InvalidConst(Const),
- InFunction(Box<MirEvalError>, Vec<(Either<FunctionId, ClosureId>, MirSpan, DefWithBodyId)>),
+ InFunction(
+ Box<MirEvalError<'db>>,
+ Vec<(Either<FunctionId, ClosureId>, MirSpan, DefWithBodyId)>,
+ ),
ExecutionLimitExceeded,
StackOverflow,
/// FIXME: Fold this into InternalError
@@ -360,7 +369,7 @@ pub enum MirEvalError {
InternalError(Box<str>),
}
-impl MirEvalError {
+impl MirEvalError<'_> {
pub fn pretty_print(
&self,
f: &mut String,
@@ -492,7 +501,7 @@ impl MirEvalError {
}
}
-impl std::fmt::Debug for MirEvalError {
+impl std::fmt::Debug for MirEvalError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ConstEvalError(arg0, arg1) => {
@@ -534,7 +543,7 @@ impl std::fmt::Debug for MirEvalError {
}
}
-type Result<T> = std::result::Result<T, MirEvalError>;
+type Result<'db, T> = std::result::Result<T, MirEvalError<'db>>;
#[derive(Debug, Default)]
struct DropFlags {
@@ -595,10 +604,10 @@ pub fn interpret_mir<'db>(
// (and probably should) do better here, for example by excluding bindings outside of the target expression.
assert_placeholder_ty_is_unused: bool,
trait_env: Option<Arc<TraitEnvironment<'db>>>,
-) -> Result<(Result<Const>, MirOutput)> {
+) -> Result<'db, (Result<'db, Const>, MirOutput)> {
let ty = body.locals[return_slot()].ty.clone();
let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?;
- let it: Result<Const> = (|| {
+ let it: Result<'db, Const> = (|| {
if evaluator.ptr_size() != size_of::<usize>() {
not_supported!("targets with different pointer size from host");
}
@@ -639,13 +648,14 @@ impl<'db> Evaluator<'db> {
owner: DefWithBodyId,
assert_placeholder_ty_is_unused: bool,
trait_env: Option<Arc<TraitEnvironment<'db>>>,
- ) -> Result<Evaluator<'db>> {
+ ) -> Result<'db, Evaluator<'db>> {
let crate_id = owner.module(db).krate();
let target_data_layout = match db.target_data_layout(crate_id) {
Ok(target_data_layout) => target_data_layout,
Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)),
};
let cached_ptr_size = target_data_layout.pointer_size().bytes_usize();
+ let interner = DbInterner::new_with(db, None, None);
Ok(Evaluator {
target_data_layout,
stack: vec![0],
@@ -679,14 +689,15 @@ impl<'db> Evaluator<'db> {
cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| {
x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once))
}),
+ interner,
})
}
- fn place_addr(&self, p: &Place, locals: &Locals) -> Result<Address> {
+ fn place_addr(&self, p: &Place, locals: &Locals) -> Result<'db, Address> {
Ok(self.place_addr_and_ty_and_metadata(p, locals)?.0)
}
- fn place_interval(&self, p: &Place, locals: &Locals) -> Result<Interval> {
+ fn place_interval(&self, p: &Place, locals: &Locals) -> Result<'db, Interval> {
let place_addr_and_ty = self.place_addr_and_ty_and_metadata(p, locals)?;
Ok(Interval {
addr: place_addr_and_ty.0,
@@ -714,14 +725,20 @@ impl<'db> Evaluator<'db> {
|c, subst, f| {
let InternedClosure(def, _) = self.db.lookup_intern_closure(c.into());
let infer = self.db.infer(def);
- let (captures, _) = infer.closure_info(&c);
+ let (captures, _) = infer.closure_info(c.into());
let parent_subst = ClosureSubst(subst).parent_subst(self.db);
captures
.get(f)
.expect("broken closure field")
.ty
- .clone()
- .substitute(Interner, &parent_subst)
+ .instantiate(
+ self.interner,
+ <_ as ChalkToNextSolver<'db, crate::next_solver::GenericArgs<'db>>>::to_nextsolver(
+ &parent_subst,
+ self.interner,
+ ),
+ )
+ .to_chalk(self.interner)
},
self.crate_id,
);
@@ -733,7 +750,7 @@ impl<'db> Evaluator<'db> {
&'a self,
p: &Place,
locals: &'a Locals,
- ) -> Result<(Address, Ty, Option<IntervalOrOwned>)> {
+ ) -> Result<'db, (Address, Ty, Option<IntervalOrOwned>)> {
let interner = DbInterner::new_with(self.db, None, None);
let mut addr = locals.ptr[p.local].addr;
let mut ty: Ty = locals.body.locals[p.local].ty.clone();
@@ -851,7 +868,7 @@ impl<'db> Evaluator<'db> {
Ok((addr, ty, metadata))
}
- fn layout(&self, ty: crate::next_solver::Ty<'db>) -> Result<Arc<Layout>> {
+ fn layout(&self, ty: crate::next_solver::Ty<'db>) -> Result<'db, Arc<Layout>> {
if let Some(x) = self.layout_cache.borrow().get(&ty) {
return Ok(x.clone());
}
@@ -864,7 +881,7 @@ impl<'db> Evaluator<'db> {
Ok(r)
}
- fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<Arc<Layout>> {
+ fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<'db, Arc<Layout>> {
let interner = DbInterner::new_with(self.db, None, None);
self.layout(crate::next_solver::Ty::new(
interner,
@@ -875,22 +892,27 @@ impl<'db> Evaluator<'db> {
))
}
- fn place_ty<'a>(&'a self, p: &Place, locals: &'a Locals) -> Result<Ty> {
+ fn place_ty<'a>(&'a self, p: &Place, locals: &'a Locals) -> Result<'db, Ty> {
Ok(self.place_addr_and_ty_and_metadata(p, locals)?.1)
}
- fn operand_ty(&self, o: &Operand, locals: &Locals) -> Result<Ty> {
+ fn operand_ty(&self, o: &Operand, locals: &Locals) -> Result<'db, Ty> {
Ok(match &o.kind {
OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?,
OperandKind::Constant(c) => c.data(Interner).ty.clone(),
&OperandKind::Static(s) => {
- let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr].clone();
+ let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr]
+ .to_chalk(self.interner);
TyKind::Ref(Mutability::Not, static_lifetime(), ty).intern(Interner)
}
})
}
- fn operand_ty_and_eval(&mut self, o: &Operand, locals: &mut Locals) -> Result<IntervalAndTy> {
+ fn operand_ty_and_eval(
+ &mut self,
+ o: &Operand,
+ locals: &mut Locals,
+ ) -> Result<'db, IntervalAndTy> {
Ok(IntervalAndTy {
interval: self.eval_operand(o, locals)?,
ty: self.operand_ty(o, locals)?,
@@ -901,7 +923,7 @@ impl<'db> Evaluator<'db> {
&mut self,
body: Arc<MirBody>,
args: impl Iterator<Item = IntervalOrOwned>,
- ) -> Result<Interval> {
+ ) -> Result<'db, Interval> {
if let Some(it) = self.stack_depth_limit.checked_sub(1) {
self.stack_depth_limit = it;
} else {
@@ -962,7 +984,7 @@ impl<'db> Evaluator<'db> {
let args = args
.iter()
.map(|it| self.operand_ty_and_eval(it, locals))
- .collect::<Result<Vec<_>>>()?;
+ .collect::<Result<'db, Vec<_>>>()?;
let stack_frame = match &fn_ty.kind(Interner) {
TyKind::Function(_) => {
let bytes = self.eval_operand(func, locals)?;
@@ -1066,7 +1088,7 @@ impl<'db> Evaluator<'db> {
body: &MirBody,
locals: &mut Locals,
args: impl Iterator<Item = IntervalOrOwned>,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
let mut remain_args = body.param_locals.len();
for ((l, interval), value) in locals.ptr.iter().skip(1).zip(args) {
locals.drop_flags.add_place(l.into(), &locals.body.projection_store);
@@ -1089,7 +1111,7 @@ impl<'db> Evaluator<'db> {
&mut self,
body: &Arc<MirBody>,
destination: Option<Interval>,
- ) -> Result<(Locals, usize)> {
+ ) -> Result<'db, (Locals, usize)> {
let mut locals =
match self.unused_locals_store.borrow_mut().entry(body.owner).or_default().pop() {
None => Locals {
@@ -1136,7 +1158,7 @@ impl<'db> Evaluator<'db> {
Ok((locals, prev_stack_pointer))
}
- fn eval_rvalue(&mut self, r: &Rvalue, locals: &mut Locals) -> Result<IntervalOrOwned> {
+ fn eval_rvalue(&mut self, r: &Rvalue, locals: &mut Locals) -> Result<'db, IntervalOrOwned> {
let interner = DbInterner::new_with(self.db, None, None);
use IntervalOrOwned::*;
Ok(match r {
@@ -1450,7 +1472,7 @@ impl<'db> Evaluator<'db> {
let values = values
.iter()
.map(|it| self.eval_operand(it, locals))
- .collect::<Result<Vec<_>>>()?;
+ .collect::<Result<'db, Vec<_>>>()?;
match kind {
AggregateKind::Array(_) => {
let mut r = vec![];
@@ -1649,7 +1671,7 @@ impl<'db> Evaluator<'db> {
})
}
- fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> {
+ fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<'db, i128> {
let interner = DbInterner::new_with(self.db, None, None);
let layout = self.layout(ty.to_nextsolver(interner))?;
let &TyKind::Adt(chalk_ir::AdtId(AdtId::EnumId(e)), _) = ty.kind(Interner) else {
@@ -1696,7 +1718,7 @@ impl<'db> Evaluator<'db> {
&self,
ty: &Ty,
goal: impl Fn(&TyKind) -> Option<T>,
- ) -> Result<T> {
+ ) -> Result<'db, T> {
let kind = ty.kind(Interner);
if let Some(it) = goal(kind) {
return Ok(it);
@@ -1719,7 +1741,7 @@ impl<'db> Evaluator<'db> {
addr: Interval,
current_ty: &Ty,
target_ty: &Ty,
- ) -> Result<IntervalOrOwned> {
+ ) -> Result<'db, IntervalOrOwned> {
fn for_ptr(it: &TyKind) -> Option<Ty> {
match it {
TyKind::Raw(_, ty) | TyKind::Ref(_, _, ty) => Some(ty.clone()),
@@ -1738,7 +1760,7 @@ impl<'db> Evaluator<'db> {
target_ty: Ty,
current_ty: Ty,
addr: Interval,
- ) -> Result<IntervalOrOwned> {
+ ) -> Result<'db, IntervalOrOwned> {
use IntervalOrOwned::*;
Ok(match &target_ty.kind(Interner) {
TyKind::Slice(_) => match &current_ty.kind(Interner) {
@@ -1806,7 +1828,7 @@ impl<'db> Evaluator<'db> {
it: VariantId,
subst: Substitution,
locals: &Locals,
- ) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> {
+ ) -> Result<'db, (usize, Arc<Layout>, Option<(usize, usize, i128)>)> {
let interner = DbInterner::new_with(self.db, None, None);
let adt = it.adt_id(self.db);
if let DefWithBodyId::VariantId(f) = locals.body.owner
@@ -1874,7 +1896,7 @@ impl<'db> Evaluator<'db> {
variant_layout: &Layout,
tag: Option<(usize, usize, i128)>,
values: impl Iterator<Item = IntervalOrOwned>,
- ) -> Result<Vec<u8>> {
+ ) -> Result<'db, Vec<u8>> {
let mut result = vec![0; size];
if let Some((offset, size, value)) = tag {
match result.get_mut(offset..offset + size) {
@@ -1904,7 +1926,7 @@ impl<'db> Evaluator<'db> {
Ok(result)
}
- fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result<Interval> {
+ fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result<'db, Interval> {
Ok(match &it.kind {
OperandKind::Copy(p) | OperandKind::Move(p) => {
locals.drop_flags.remove_place(p, &locals.body.projection_store);
@@ -1919,8 +1941,8 @@ impl<'db> Evaluator<'db> {
}
#[allow(clippy::double_parens)]
- fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<Interval> {
- let interner = DbInterner::new_with(self.db, None, None);
+ fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<'db, Interval> {
+ let interner = self.interner;
let ConstData { ty, value: chalk_ir::ConstValue::Concrete(c) } = &konst.data(Interner)
else {
not_supported!("evaluating non concrete constant");
@@ -1932,9 +1954,14 @@ impl<'db> Evaluator<'db> {
let mut const_id = *const_id;
let mut subst = subst.clone();
if let hir_def::GeneralConstId::ConstId(c) = const_id {
- let (c, s) = lookup_impl_const(self.db, self.trait_env.clone(), c, subst);
+ let (c, s) = lookup_impl_const(
+ self.interner,
+ self.trait_env.clone(),
+ c,
+ subst.to_nextsolver(self.interner),
+ );
const_id = hir_def::GeneralConstId::ConstId(c);
- subst = s;
+ subst = s.to_chalk(self.interner);
}
result_owner = self
.db
@@ -1987,7 +2014,7 @@ impl<'db> Evaluator<'db> {
Ok(Interval::new(addr, size))
}
- fn eval_place(&mut self, p: &Place, locals: &Locals) -> Result<Interval> {
+ fn eval_place(&mut self, p: &Place, locals: &Locals) -> Result<'db, Interval> {
let addr = self.place_addr(p, locals)?;
Ok(Interval::new(
addr,
@@ -1995,7 +2022,7 @@ impl<'db> Evaluator<'db> {
))
}
- fn read_memory(&self, addr: Address, size: usize) -> Result<&[u8]> {
+ fn read_memory(&self, addr: Address, size: usize) -> Result<'db, &[u8]> {
if size == 0 {
return Ok(&[]);
}
@@ -2012,7 +2039,7 @@ impl<'db> Evaluator<'db> {
.ok_or_else(|| MirEvalError::UndefinedBehavior("out of bound memory read".to_owned()))
}
- fn write_memory_using_ref(&mut self, addr: Address, size: usize) -> Result<&mut [u8]> {
+ fn write_memory_using_ref(&mut self, addr: Address, size: usize) -> Result<'db, &mut [u8]> {
let (mem, pos) = match addr {
Stack(it) => (&mut self.stack, it),
Heap(it) => (&mut self.heap, it),
@@ -2026,7 +2053,7 @@ impl<'db> Evaluator<'db> {
.ok_or_else(|| MirEvalError::UndefinedBehavior("out of bound memory write".to_owned()))
}
- fn write_memory(&mut self, addr: Address, r: &[u8]) -> Result<()> {
+ fn write_memory(&mut self, addr: Address, r: &[u8]) -> Result<'db, ()> {
if r.is_empty() {
return Ok(());
}
@@ -2034,14 +2061,18 @@ impl<'db> Evaluator<'db> {
Ok(())
}
- fn copy_from_interval_or_owned(&mut self, addr: Address, r: IntervalOrOwned) -> Result<()> {
+ fn copy_from_interval_or_owned(
+ &mut self,
+ addr: Address,
+ r: IntervalOrOwned,
+ ) -> Result<'db, ()> {
match r {
IntervalOrOwned::Borrowed(r) => self.copy_from_interval(addr, r),
IntervalOrOwned::Owned(r) => self.write_memory(addr, &r),
}
}
- fn copy_from_interval(&mut self, addr: Address, r: Interval) -> Result<()> {
+ fn copy_from_interval(&mut self, addr: Address, r: Interval) -> Result<'db, ()> {
if r.size == 0 {
return Ok(());
}
@@ -2083,7 +2114,7 @@ impl<'db> Evaluator<'db> {
Ok(())
}
- fn size_align_of(&self, ty: &Ty, locals: &Locals) -> Result<Option<(usize, usize)>> {
+ fn size_align_of(&self, ty: &Ty, locals: &Locals) -> Result<'db, Option<(usize, usize)>> {
let interner = DbInterner::new_with(self.db, None, None);
if let Some(layout) = self.layout_cache.borrow().get(&ty.to_nextsolver(interner)) {
return Ok(layout
@@ -2112,7 +2143,7 @@ impl<'db> Evaluator<'db> {
/// A version of `self.size_of` which returns error if the type is unsized. `what` argument should
/// be something that complete this: `error: type {ty} was unsized. {what} should be sized`
- fn size_of_sized(&self, ty: &Ty, locals: &Locals, what: &'static str) -> Result<usize> {
+ fn size_of_sized(&self, ty: &Ty, locals: &Locals, what: &'static str) -> Result<'db, usize> {
match self.size_align_of(ty, locals)? {
Some(it) => Ok(it.0),
None => Err(MirEvalError::TypeIsUnsized(ty.clone(), what)),
@@ -2126,14 +2157,14 @@ impl<'db> Evaluator<'db> {
ty: &Ty,
locals: &Locals,
what: &'static str,
- ) -> Result<(usize, usize)> {
+ ) -> Result<'db, (usize, usize)> {
match self.size_align_of(ty, locals)? {
Some(it) => Ok(it),
None => Err(MirEvalError::TypeIsUnsized(ty.clone(), what)),
}
}
- fn heap_allocate(&mut self, size: usize, align: usize) -> Result<Address> {
+ fn heap_allocate(&mut self, size: usize, align: usize) -> Result<'db, Address> {
if !align.is_power_of_two() || align > 10000 {
return Err(MirEvalError::UndefinedBehavior(format!("Alignment {align} is invalid")));
}
@@ -2166,7 +2197,7 @@ impl<'db> Evaluator<'db> {
bytes: &[u8],
ty: &Ty,
locals: &Locals,
- ) -> Result<ComplexMemoryMap<'db>> {
+ ) -> Result<'db, ComplexMemoryMap<'db>> {
fn rec<'db>(
this: &Evaluator<'db>,
bytes: &[u8],
@@ -2174,7 +2205,7 @@ impl<'db> Evaluator<'db> {
locals: &Locals,
mm: &mut ComplexMemoryMap<'db>,
stack_depth_limit: usize,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
let interner = DbInterner::new_with(this.db, None, None);
if stack_depth_limit.checked_sub(1).is_none() {
return Err(MirEvalError::StackOverflow);
@@ -2333,11 +2364,11 @@ impl<'db> Evaluator<'db> {
fn patch_addresses(
&mut self,
patch_map: &FxHashMap<usize, usize>,
- ty_of_bytes: impl Fn(&[u8]) -> Result<crate::next_solver::Ty<'db>> + Copy,
+ ty_of_bytes: impl Fn(&[u8]) -> Result<'db, crate::next_solver::Ty<'db>> + Copy,
addr: Address,
ty: crate::next_solver::Ty<'db>,
locals: &Locals,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
let interner = DbInterner::new_with(self.db, None, None);
// FIXME: support indirect references
let layout = self.layout(ty)?;
@@ -2469,7 +2500,7 @@ impl<'db> Evaluator<'db> {
locals: &Locals,
target_bb: Option<BasicBlockId>,
span: MirSpan,
- ) -> Result<Option<StackFrame>> {
+ ) -> Result<'db, Option<StackFrame>> {
let id = from_bytes!(usize, bytes.get(self)?);
let next_ty = self.vtable_map.ty(id)?;
let interner = DbInterner::new_with(self.db, None, None);
@@ -2506,7 +2537,7 @@ impl<'db> Evaluator<'db> {
args: &[IntervalAndTy],
locals: &Locals,
span: MirSpan,
- ) -> Result<Option<StackFrame>> {
+ ) -> Result<'db, Option<StackFrame>> {
let mir_body = self
.db
.monomorphized_mir_body_for_closure(
@@ -2523,7 +2554,7 @@ impl<'db> Evaluator<'db> {
};
let arg_bytes = iter::once(Ok(closure_data))
.chain(args.iter().map(|it| Ok(it.get(self)?.to_owned())))
- .collect::<Result<Vec<_>>>()?;
+ .collect::<Result<'db, Vec<_>>>()?;
let interval = self
.interpret_mir(mir_body, arg_bytes.into_iter().map(IntervalOrOwned::Owned))
.map_err(|e| {
@@ -2545,7 +2576,7 @@ impl<'db> Evaluator<'db> {
locals: &Locals,
target_bb: Option<BasicBlockId>,
span: MirSpan,
- ) -> Result<Option<StackFrame>> {
+ ) -> Result<'db, Option<StackFrame>> {
let generic_args = generic_args.clone();
match def {
CallableDefId::FunctionId(def) => {
@@ -2603,23 +2634,33 @@ impl<'db> Evaluator<'db> {
generic_args: Substitution,
locals: &Locals,
span: MirSpan,
- ) -> Result<MirOrDynIndex> {
+ ) -> Result<'db, MirOrDynIndex> {
let pair = (def, generic_args);
if let Some(r) = self.mir_or_dyn_index_cache.borrow().get(&pair) {
return Ok(r.clone());
}
let (def, generic_args) = pair;
- let r = if let Some(self_ty_idx) =
- is_dyn_method(self.db, self.trait_env.clone(), def, generic_args.clone())
- {
+ let r = if let Some(self_ty_idx) = is_dyn_method(
+ self.interner,
+ self.trait_env.clone(),
+ def,
+ generic_args.to_nextsolver(self.interner),
+ ) {
MirOrDynIndex::Dyn(self_ty_idx)
} else {
- let (imp, generic_args) =
- self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args.clone());
+ let (imp, generic_args) = self.db.lookup_impl_method(
+ self.trait_env.clone(),
+ def,
+ generic_args.to_nextsolver(self.interner),
+ );
let mir_body = self
.db
- .monomorphized_mir_body(imp.into(), generic_args, self.trait_env.clone())
+ .monomorphized_mir_body(
+ imp.into(),
+ generic_args.to_chalk(self.interner),
+ self.trait_env.clone(),
+ )
.map_err(|e| {
MirEvalError::InFunction(
Box::new(MirEvalError::MirLowerError(imp, e)),
@@ -2641,7 +2682,7 @@ impl<'db> Evaluator<'db> {
destination: Interval,
target_bb: Option<BasicBlockId>,
span: MirSpan,
- ) -> Result<Option<StackFrame>> {
+ ) -> Result<'db, Option<StackFrame>> {
let interner = DbInterner::new_with(self.db, None, None);
if self.detect_and_exec_special_function(
def,
@@ -2713,7 +2754,7 @@ impl<'db> Evaluator<'db> {
span: MirSpan,
destination: Interval,
target_bb: Option<BasicBlockId>,
- ) -> Result<Option<StackFrame>> {
+ ) -> Result<'db, Option<StackFrame>> {
Ok(if let Some(target_bb) = target_bb {
let (mut locals, prev_stack_ptr) =
self.create_locals_for_body(&mir_body, Some(destination))?;
@@ -2741,7 +2782,7 @@ impl<'db> Evaluator<'db> {
destination: Interval,
target_bb: Option<BasicBlockId>,
span: MirSpan,
- ) -> Result<Option<StackFrame>> {
+ ) -> Result<'db, Option<StackFrame>> {
let interner = DbInterner::new_with(self.db, None, None);
let func = args
.first()
@@ -2817,7 +2858,7 @@ impl<'db> Evaluator<'db> {
}
}
- fn eval_static(&mut self, st: StaticId, locals: &Locals) -> Result<Address> {
+ fn eval_static(&mut self, st: StaticId, locals: &Locals) -> Result<'db, Address> {
if let Some(o) = self.static_locations.get(&st) {
return Ok(*o);
};
@@ -2828,8 +2869,9 @@ impl<'db> Evaluator<'db> {
})?;
self.allocate_const_in_heap(locals, &konst)?
} else {
- let ty = &self.db.infer(st.into())[self.db.body(st.into()).body_expr];
- let Some((size, align)) = self.size_align_of(ty, locals)? else {
+ let ty =
+ self.db.infer(st.into())[self.db.body(st.into()).body_expr].to_chalk(self.interner);
+ let Some((size, align)) = self.size_align_of(&ty, locals)? else {
not_supported!("unsized extern static");
};
let addr = self.heap_allocate(size, align)?;
@@ -2841,7 +2883,7 @@ impl<'db> Evaluator<'db> {
Ok(addr)
}
- fn const_eval_discriminant(&self, variant: EnumVariantId) -> Result<i128> {
+ fn const_eval_discriminant(&self, variant: EnumVariantId) -> Result<'db, i128> {
let r = self.db.const_eval_discriminant(variant);
match r {
Ok(r) => Ok(r),
@@ -2863,7 +2905,7 @@ impl<'db> Evaluator<'db> {
}
}
- fn drop_place(&mut self, place: &Place, locals: &mut Locals, span: MirSpan) -> Result<()> {
+ fn drop_place(&mut self, place: &Place, locals: &mut Locals, span: MirSpan) -> Result<'db, ()> {
let (addr, ty, metadata) = self.place_addr_and_ty_and_metadata(place, locals)?;
if !locals.drop_flags.remove_place(place, &locals.body.projection_store) {
return Ok(());
@@ -2882,7 +2924,7 @@ impl<'db> Evaluator<'db> {
addr: Address,
_metadata: &[u8],
span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
let Some(drop_fn) = (|| {
let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?;
drop_trait.trait_items(self.db).method_by_name(&Name::new_symbol_root(sym::drop))
@@ -2962,22 +3004,22 @@ impl<'db> Evaluator<'db> {
Ok(())
}
- fn write_to_stdout(&mut self, interval: Interval) -> Result<()> {
+ fn write_to_stdout(&mut self, interval: Interval) -> Result<'db, ()> {
self.stdout.extend(interval.get(self)?.to_vec());
Ok(())
}
- fn write_to_stderr(&mut self, interval: Interval) -> Result<()> {
+ fn write_to_stderr(&mut self, interval: Interval) -> Result<'db, ()> {
self.stderr.extend(interval.get(self)?.to_vec());
Ok(())
}
}
-pub fn render_const_using_debug_impl(
- db: &dyn HirDatabase,
+pub fn render_const_using_debug_impl<'db>(
+ db: &'db dyn HirDatabase,
owner: DefWithBodyId,
c: &Const,
-) -> Result<String> {
+) -> Result<'db, String> {
let interner = DbInterner::new_with(db, None, None);
let mut evaluator = Evaluator::new(db, owner, false, None)?;
let locals = &Locals {
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index bb0d1f70fb..4653610edd 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -49,7 +49,7 @@ macro_rules! not_supported {
};
}
-impl Evaluator<'_> {
+impl<'db> Evaluator<'db> {
pub(super) fn detect_and_exec_special_function(
&mut self,
def: FunctionId,
@@ -58,7 +58,7 @@ impl Evaluator<'_> {
locals: &Locals,
destination: Interval,
span: MirSpan,
- ) -> Result<bool> {
+ ) -> Result<'db, bool> {
if self.not_special_fn_cache.borrow().contains(&def) {
return Ok(false);
}
@@ -142,7 +142,7 @@ impl Evaluator<'_> {
pub(super) fn detect_and_redirect_special_function(
&mut self,
def: FunctionId,
- ) -> Result<Option<FunctionId>> {
+ ) -> Result<'db, Option<FunctionId>> {
// `PanicFmt` is redirected to `ConstPanicFmt`
if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
let resolver = CrateRootModuleId::from(self.crate_id).resolver(self.db);
@@ -166,8 +166,8 @@ impl Evaluator<'_> {
locals: &Locals,
destination: Interval,
span: MirSpan,
- ) -> Result<()> {
- let interner = DbInterner::new_with(self.db, None, None);
+ ) -> Result<'db, ()> {
+ let interner = self.interner;
match self_ty.kind(Interner) {
TyKind::Function(_) => {
let [arg] = args else {
@@ -184,9 +184,12 @@ impl Evaluator<'_> {
let addr = Address::from_bytes(arg.get(self)?)?;
let InternedClosure(closure_owner, _) = self.db.lookup_intern_closure((*id).into());
let infer = self.db.infer(closure_owner);
- let (captures, _) = infer.closure_info(id);
+ let (captures, _) = infer.closure_info((*id).into());
let layout = self.layout(self_ty.to_nextsolver(interner))?;
- let ty_iter = captures.iter().map(|c| c.ty(self.db, subst));
+ let db = self.db;
+ let ty_iter = captures
+ .iter()
+ .map(|c| c.ty(db, subst.to_nextsolver(interner)).to_chalk(interner));
self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?;
}
TyKind::Tuple(_, subst) => {
@@ -222,7 +225,7 @@ impl Evaluator<'_> {
locals: &Locals,
destination: Interval,
span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
let interner = DbInterner::new_with(self.db, None, None);
for (i, ty) in ty_iter.enumerate() {
let size = self.layout(ty.to_nextsolver(interner))?.size.bytes_usize();
@@ -250,7 +253,7 @@ impl Evaluator<'_> {
alloc_fn: &Symbol,
args: &[IntervalAndTy],
destination: Interval,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
match alloc_fn {
_ if *alloc_fn == sym::rustc_allocator_zeroed || *alloc_fn == sym::rustc_allocator => {
let [size, align] = args else {
@@ -314,7 +317,7 @@ impl Evaluator<'_> {
args: &[IntervalAndTy],
locals: &Locals,
span: MirSpan,
- ) -> Result<Vec<u8>> {
+ ) -> Result<'db, Vec<u8>> {
use LangItem::*;
let mut args = args.iter();
match it {
@@ -391,7 +394,7 @@ impl Evaluator<'_> {
destination: Interval,
_locals: &Locals,
_span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
match id {
318 => {
// SYS_getrandom
@@ -422,7 +425,7 @@ impl Evaluator<'_> {
destination: Interval,
locals: &Locals,
span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
match as_str {
"memcmp" => {
let [ptr1, ptr2, size] = args else {
@@ -589,7 +592,7 @@ impl Evaluator<'_> {
locals: &Locals,
span: MirSpan,
needs_override: bool,
- ) -> Result<bool> {
+ ) -> Result<'db, bool> {
let interner = DbInterner::new_with(self.db, None, None);
if let Some(name) = name.strip_prefix("atomic_") {
return self
@@ -1405,7 +1408,7 @@ impl Evaluator<'_> {
ty: &Ty,
metadata: Interval,
locals: &Locals,
- ) -> Result<(usize, usize)> {
+ ) -> Result<'db, (usize, usize)> {
let interner = DbInterner::new_with(self.db, None, None);
Ok(match ty.kind(Interner) {
TyKind::Str => (from_bytes!(usize, metadata.get(self)?), 1),
@@ -1461,7 +1464,7 @@ impl Evaluator<'_> {
destination: Interval,
locals: &Locals,
_span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
let interner = DbInterner::new_with(self.db, None, None);
// We are a single threaded runtime with no UB checking and no optimization, so
// we can implement atomic intrinsics as normal functions.
diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs
index f554772904..8e62c764b9 100644
--- a/crates/hir-ty/src/mir/eval/shim/simd.rs
+++ b/crates/hir-ty/src/mir/eval/shim/simd.rs
@@ -22,8 +22,8 @@ macro_rules! not_supported {
};
}
-impl Evaluator<'_> {
- fn detect_simd_ty(&self, ty: &Ty) -> Result<(usize, Ty)> {
+impl<'db> Evaluator<'db> {
+ fn detect_simd_ty(&self, ty: &Ty) -> Result<'db, (usize, Ty)> {
match ty.kind(Interner) {
TyKind::Adt(id, subst) => {
let len = match subst.as_slice(Interner).get(1).and_then(|it| it.constant(Interner))
@@ -74,7 +74,7 @@ impl Evaluator<'_> {
destination: Interval,
_locals: &Locals,
_span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
match name {
"and" | "or" | "xor" => {
let [left, right] = args else {
diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs
index 2a6e3a147a..9e948d1b43 100644
--- a/crates/hir-ty/src/mir/eval/tests.rs
+++ b/crates/hir-ty/src/mir/eval/tests.rs
@@ -11,7 +11,7 @@ use crate::{
use super::{MirEvalError, interpret_mir};
-fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError> {
+fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError<'_>> {
salsa::attach(db, || {
let module_id = db.module_for_file(file_id.file_id(db));
let def_map = module_id.def_map(db);
@@ -114,7 +114,7 @@ fn check_panic(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_panic:
fn check_error_with(
#[rust_analyzer::rust_fixture] ra_fixture: &str,
- expect_err: impl FnOnce(MirEvalError) -> bool,
+ expect_err: impl FnOnce(MirEvalError<'_>) -> bool,
) {
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
salsa::attach(&db, || {
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 3e44e8c68d..ec7bff7082 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -20,6 +20,7 @@ use hir_expand::name::Name;
use la_arena::ArenaMap;
use rustc_apfloat::Float;
use rustc_hash::FxHashMap;
+use rustc_type_ir::inherent::IntoKind;
use span::{Edition, FileId};
use syntax::TextRange;
use triomphe::Arc;
@@ -74,24 +75,25 @@ struct DropScope {
locals: Vec<LocalId>,
}
-struct MirLowerCtx<'db> {
+struct MirLowerCtx<'a, 'db> {
result: MirBody,
owner: DefWithBodyId,
current_loop_blocks: Option<LoopBlocks>,
labeled_loop_blocks: FxHashMap<LabelId, LoopBlocks>,
discr_temp: Option<Place>,
db: &'db dyn HirDatabase,
- body: &'db Body,
- infer: &'db InferenceResult,
+ body: &'a Body,
+ infer: &'a InferenceResult<'db>,
resolver: Resolver<'db>,
drop_scopes: Vec<DropScope>,
env: Arc<TraitEnvironment<'db>>,
+ interner: DbInterner<'db>,
}
// FIXME: Make this smaller, its stored in database queries
#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum MirLowerError {
- ConstEvalError(Box<str>, Box<ConstEvalError>),
+pub enum MirLowerError<'db> {
+ ConstEvalError(Box<str>, Box<ConstEvalError<'db>>),
LayoutError(LayoutError),
IncompleteExpr,
IncompletePattern,
@@ -103,7 +105,7 @@ pub enum MirLowerError {
UnresolvedField,
UnsizedTemporary(Ty),
MissingFunctionDefinition(DefWithBodyId, ExprId),
- TypeMismatch(TypeMismatch),
+ TypeMismatch(TypeMismatch<'db>),
HasErrors,
/// This should never happen. Type mismatch should catch everything.
TypeError(&'static str),
@@ -128,7 +130,7 @@ struct DropScopeToken;
impl DropScopeToken {
fn pop_and_drop(
self,
- ctx: &mut MirLowerCtx<'_>,
+ ctx: &mut MirLowerCtx<'_, '_>,
current: BasicBlockId,
span: MirSpan,
) -> BasicBlockId {
@@ -140,7 +142,7 @@ impl DropScopeToken {
/// code. Either when the control flow is diverging (so drop code doesn't reached) or when drop is handled
/// for us (for example a block that ended with a return statement. Return will drop everything, so the block shouldn't
/// do anything)
- fn pop_assume_dropped(self, ctx: &mut MirLowerCtx<'_>) {
+ fn pop_assume_dropped(self, ctx: &mut MirLowerCtx<'_, '_>) {
std::mem::forget(self);
ctx.pop_drop_scope_assume_dropped_internal();
}
@@ -161,7 +163,7 @@ impl Drop for DropScopeToken {
// }
// }
-impl MirLowerError {
+impl MirLowerError<'_> {
pub fn pretty_print(
&self,
f: &mut String,
@@ -248,13 +250,13 @@ macro_rules! implementation_error {
}};
}
-impl From<LayoutError> for MirLowerError {
+impl From<LayoutError> for MirLowerError<'_> {
fn from(value: LayoutError) -> Self {
MirLowerError::LayoutError(value)
}
}
-impl MirLowerError {
+impl MirLowerError<'_> {
fn unresolved_path(
db: &dyn HirDatabase,
p: &Path,
@@ -267,14 +269,14 @@ impl MirLowerError {
}
}
-type Result<T> = std::result::Result<T, MirLowerError>;
+type Result<'db, T> = std::result::Result<T, MirLowerError<'db>>;
-impl<'ctx> MirLowerCtx<'ctx> {
+impl<'a, 'db> MirLowerCtx<'a, 'db> {
fn new(
- db: &'ctx dyn HirDatabase,
+ db: &'db dyn HirDatabase,
owner: DefWithBodyId,
- body: &'ctx Body,
- infer: &'ctx InferenceResult,
+ body: &'a Body,
+ infer: &'a InferenceResult<'db>,
) -> Self {
let mut basic_blocks = Arena::new();
let start_block = basic_blocks.alloc(BasicBlock {
@@ -296,6 +298,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
};
let resolver = owner.resolver(db);
let env = db.trait_environment_for_body(owner);
+ let interner = DbInterner::new_with(db, Some(env.krate), env.block);
MirLowerCtx {
result: mir,
@@ -309,10 +312,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
discr_temp: None,
drop_scopes: vec![DropScope::default()],
env,
+ interner,
}
}
- fn temp(&mut self, ty: Ty, current: BasicBlockId, span: MirSpan) -> Result<LocalId> {
+ fn temp(&mut self, ty: Ty, current: BasicBlockId, span: MirSpan) -> Result<'db, LocalId> {
if matches!(ty.kind(Interner), TyKind::Slice(_) | TyKind::Dyn(_)) {
return Err(MirLowerError::UnsizedTemporary(ty));
}
@@ -325,7 +329,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
&mut self,
expr_id: ExprId,
current: BasicBlockId,
- ) -> Result<Option<(Operand, BasicBlockId)>> {
+ ) -> Result<'db, Option<(Operand, BasicBlockId)>> {
if !self.has_adjustments(expr_id)
&& let Expr::Literal(l) = &self.body[expr_id]
{
@@ -343,8 +347,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
expr_id: ExprId,
place: Place,
current: BasicBlockId,
- adjustments: &[Adjustment],
- ) -> Result<Option<BasicBlockId>> {
+ adjustments: &[Adjustment<'db>],
+ ) -> Result<'db, Option<BasicBlockId>> {
match adjustments.split_last() {
Some((last, rest)) => match &last.kind {
Adjust::NeverToAny => {
@@ -372,7 +376,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
else {
return Ok(None);
};
- let bk = BorrowKind::from_chalk(*m);
+ let bk = BorrowKind::from_rustc(*m);
self.push_assignment(current, place, Rvalue::Ref(bk, p), expr_id.into());
Ok(Some(current))
}
@@ -388,7 +392,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
Rvalue::Cast(
CastKind::PointerCoercion(*cast),
Operand { kind: OperandKind::Copy(p), span: None },
- last.target.clone(),
+ last.target.to_chalk(self.interner),
),
expr_id.into(),
);
@@ -404,7 +408,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
expr_id: ExprId,
place: Place,
prev_block: BasicBlockId,
- ) -> Result<Option<BasicBlockId>> {
+ ) -> Result<'db, Option<BasicBlockId>> {
if let Some(adjustments) = self.infer.expr_adjustments.get(&expr_id) {
return self.lower_expr_to_place_with_adjust(expr_id, place, prev_block, adjustments);
}
@@ -416,7 +420,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
expr_id: ExprId,
place: Place,
mut current: BasicBlockId,
- ) -> Result<Option<BasicBlockId>> {
+ ) -> Result<'db, Option<BasicBlockId>> {
match &self.body[expr_id] {
Expr::OffsetOf(_) => {
not_supported!("builtin#offset_of")
@@ -443,7 +447,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
c.into(),
current,
place,
- subst,
+ subst.to_chalk(self.interner),
expr_id.into(),
self.expr_ty_without_adjust(expr_id),
)?;
@@ -511,12 +515,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
ValueNs::EnumVariantId(variant_id) => {
let variant_fields = variant_id.fields(self.db);
if variant_fields.shape == FieldsShape::Unit {
- let ty = self.infer.type_of_expr[expr_id].clone();
+ let ty = self.infer.type_of_expr[expr_id];
current = self.lower_enum_variant(
variant_id,
current,
place,
- ty,
+ ty.to_chalk(self.interner),
Box::new([]),
expr_id.into(),
)?;
@@ -651,7 +655,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
if let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id) {
let ty = chalk_ir::TyKind::FnDef(
CallableDefId::FunctionId(func_id).to_chalk(self.db),
- generic_args,
+ generic_args.to_chalk(self.interner),
)
.intern(Interner);
let func = Operand::from_bytes(Box::default(), ty);
@@ -710,7 +714,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
method_name.display(self.db, self.edition()).to_string(),
)
})?;
- let func = Operand::from_fn(self.db, func_id, generic_args);
+ let func = Operand::from_fn(self.db, func_id, generic_args.to_chalk(self.interner));
self.lower_call_and_args(
func,
iter::once(*receiver).chain(args.iter().copied()),
@@ -948,8 +952,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
let rvalue = if self.infer.coercion_casts.contains(expr) {
Rvalue::Use(it)
} else {
- let source_ty = self.infer[*expr].clone();
- let target_ty = self.infer[expr_id].clone();
+ let source_ty = self.infer[*expr].to_chalk(self.interner);
+ let target_ty = self.infer[expr_id].to_chalk(self.interner);
let cast_kind = if source_ty.as_reference().is_some() {
CastKind::PointerCoercion(PointerCast::ArrayToPointer)
} else {
@@ -1047,7 +1051,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
if !is_builtin
&& let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id)
{
- let func = Operand::from_fn(self.db, func_id, generic_args);
+ let func =
+ Operand::from_fn(self.db, func_id, generic_args.to_chalk(self.interner));
return self.lower_call_and_args(
func,
[*lhs, *rhs].into_iter(),
@@ -1195,7 +1200,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
};
o.ok_or(MirLowerError::UnresolvedField)
})
- .collect::<Result<_>>()?,
+ .collect::<Result<'_, _>>()?,
),
expr_id.into(),
);
@@ -1207,7 +1212,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
not_supported!("closure with non closure type");
};
self.result.closures.push(*id);
- let (captures, _) = self.infer.closure_info(id);
+ let (captures, _) = self.infer.closure_info((*id).into());
let mut operands = vec![];
for capture in captures.iter() {
let p = Place {
@@ -1231,7 +1236,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
ProjectionElem::Subslice { from, to }
}
ProjectionElem::OpaqueCast(it) => {
- ProjectionElem::OpaqueCast(it)
+ ProjectionElem::OpaqueCast(it.to_chalk(self.interner))
}
#[allow(unreachable_patterns)]
ProjectionElem::Index(it) => match it {},
@@ -1241,9 +1246,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
};
match &capture.kind {
CaptureKind::ByRef(bk) => {
- let placeholder_subst = self.placeholder_subst();
- let tmp_ty =
- capture.ty.clone().substitute(Interner, &placeholder_subst);
+ let placeholder_subst: crate::next_solver::GenericArgs<'db> =
+ self.placeholder_subst().to_nextsolver(self.interner);
+ let tmp_ty = capture
+ .ty
+ .instantiate(self.interner, placeholder_subst)
+ .to_chalk(self.interner);
// FIXME: Handle more than one span.
let capture_spans = capture.spans();
let tmp: Place = self.temp(tmp_ty, current, capture_spans[0])?.into();
@@ -1278,7 +1286,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
current = c;
Ok(Some(o))
})
- .collect::<Result<Option<_>>>()?
+ .collect::<Result<'_, Option<_>>>()?
else {
return Ok(None);
};
@@ -1309,7 +1317,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
current = c;
Ok(Some(o))
})
- .collect::<Result<Option<_>>>()?
+ .collect::<Result<'_, Option<_>>>()?
else {
return Ok(None);
};
@@ -1353,7 +1361,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
}
- fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<()> {
+ fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<'db, ()> {
if let Expr::Field { expr, name } = &self.body[expr_id] {
if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind(Interner) {
let index =
@@ -1378,7 +1386,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
Ok(())
}
- fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result<Operand> {
+ fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result<'db, Operand> {
match &self.body[*loc] {
Expr::Literal(l) => self.lower_literal_to_operand(ty, l),
Expr::Path(c) => {
@@ -1415,7 +1423,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
}
- fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> {
+ fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<'db, Operand> {
let interner = DbInterner::new_with(self.db, None, None);
let size = || {
self.db
@@ -1479,7 +1487,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
subst: Substitution,
span: MirSpan,
ty: Ty,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
let c = self.lower_const_to_operand(subst, const_id, ty)?;
self.push_assignment(prev_block, place, c.into(), span);
Ok(())
@@ -1490,7 +1498,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
subst: Substitution,
const_id: GeneralConstId,
ty: Ty,
- ) -> Result<Operand> {
+ ) -> Result<'db, Operand> {
let c = if subst.len(Interner) != 0 {
// We can't evaluate constant with substitution now, as generics are not monomorphized in lowering.
intern_const_scalar(ConstScalar::UnevaluatedConst(const_id, subst), ty)
@@ -1510,7 +1518,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
cv: Box<[u8]>,
ty: Ty,
span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
self.push_assignment(prev_block, place, Operand::from_bytes(cv, ty).into(), span);
Ok(())
}
@@ -1523,7 +1531,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
ty: Ty,
fields: Box<[Operand]>,
span: MirSpan,
- ) -> Result<BasicBlockId> {
+ ) -> Result<'db, BasicBlockId> {
let subst = match ty.kind(Interner) {
TyKind::Adt(_, subst) => subst.clone(),
_ => implementation_error!("Non ADT enum"),
@@ -1545,7 +1553,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
mut current: BasicBlockId,
is_uninhabited: bool,
span: MirSpan,
- ) -> Result<Option<BasicBlockId>> {
+ ) -> Result<'db, Option<BasicBlockId>> {
let Some(args) = args
.map(|arg| {
if let Some((temp, c)) = self.lower_expr_to_some_operand(arg, current)? {
@@ -1555,7 +1563,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
Ok(None)
}
})
- .collect::<Result<Option<Vec<_>>>>()?
+ .collect::<Result<'_, Option<Vec<_>>>>()?
else {
return Ok(None);
};
@@ -1570,7 +1578,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
current: BasicBlockId,
is_uninhabited: bool,
span: MirSpan,
- ) -> Result<Option<BasicBlockId>> {
+ ) -> Result<'db, Option<BasicBlockId>> {
let b = if is_uninhabited { None } else { Some(self.new_basic_block()) };
self.set_terminator(
current,
@@ -1600,7 +1608,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
fn expr_ty_without_adjust(&self, e: ExprId) -> Ty {
- self.infer[e].clone()
+ self.infer[e].to_chalk(self.interner)
}
fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty {
@@ -1608,7 +1616,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
if let Some(it) = self.infer.expr_adjustments.get(&e)
&& let Some(it) = it.last()
{
- ty = Some(it.target.clone());
+ ty = Some(it.target.to_chalk(self.interner));
}
ty.unwrap_or_else(|| self.expr_ty_without_adjust(e))
}
@@ -1651,8 +1659,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
place: Place,
label: Option<LabelId>,
span: MirSpan,
- f: impl FnOnce(&mut MirLowerCtx<'_>, BasicBlockId) -> Result<()>,
- ) -> Result<Option<BasicBlockId>> {
+ f: impl FnOnce(&mut MirLowerCtx<'_, 'db>, BasicBlockId) -> Result<'db, ()>,
+ ) -> Result<'db, Option<BasicBlockId>> {
let begin = self.new_basic_block();
let prev = self.current_loop_blocks.replace(LoopBlocks {
begin,
@@ -1703,7 +1711,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
}
- fn current_loop_end(&mut self) -> Result<BasicBlockId> {
+ fn current_loop_end(&mut self) -> Result<'db, BasicBlockId> {
let r = match self
.current_loop_blocks
.as_mut()
@@ -1730,7 +1738,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
fn is_uninhabited(&self, expr_id: ExprId) -> bool {
is_ty_uninhabited_from(
self.db,
- &self.infer[expr_id],
+ &self.infer[expr_id].to_chalk(self.interner),
self.owner.module(self.db),
self.env.clone(),
)
@@ -1738,7 +1746,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
/// This function push `StorageLive` statement for the binding, and applies changes to add `StorageDead` and
/// `Drop` in the appropriated places.
- fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId) -> Result<()> {
+ fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId) -> Result<'db, ()> {
let l = self.binding_local(b)?;
self.push_storage_live_for_local(l, current, MirSpan::BindingId(b))
}
@@ -1748,13 +1756,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
l: LocalId,
current: BasicBlockId,
span: MirSpan,
- ) -> Result<()> {
+ ) -> Result<'db, ()> {
self.drop_scopes.last_mut().unwrap().locals.push(l);
self.push_statement(current, StatementKind::StorageLive(l).with_span(span));
Ok(())
}
- fn resolve_lang_item(&self, item: LangItem) -> Result<LangItemTarget> {
+ fn resolve_lang_item(&self, item: LangItem) -> Result<'db, LangItemTarget> {
let crate_id = self.owner.module(self.db).krate();
lang_item(self.db, crate_id, item).ok_or(MirLowerError::LangItemNotFound(item))
}
@@ -1766,7 +1774,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
tail: Option<ExprId>,
place: Place,
span: MirSpan,
- ) -> Result<Option<Idx<BasicBlock>>> {
+ ) -> Result<'db, Option<Idx<BasicBlock>>> {
let scope = self.push_drop_scope();
for statement in statements.iter() {
match statement {
@@ -1842,7 +1850,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
params: impl Iterator<Item = (PatId, Ty)> + Clone,
self_binding: Option<(BindingId, Ty)>,
pick_binding: impl Fn(BindingId) -> bool,
- ) -> Result<BasicBlockId> {
+ ) -> Result<'db, BasicBlockId> {
let base_param_count = self.result.param_locals.len();
let self_binding = match self_binding {
Some((self_binding, ty)) => {
@@ -1873,9 +1881,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
continue;
}
if !self.result.binding_locals.contains_idx(id) {
- self.result
- .binding_locals
- .insert(id, self.result.locals.alloc(Local { ty: self.infer[id].clone() }));
+ self.result.binding_locals.insert(
+ id,
+ self.result.locals.alloc(Local { ty: self.infer[id].to_chalk(self.interner) }),
+ );
}
}
let mut current = self.result.start_block;
@@ -1910,7 +1919,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
Ok(current)
}
- fn binding_local(&self, b: BindingId) -> Result<LocalId> {
+ fn binding_local(&self, b: BindingId) -> Result<'db, LocalId> {
match self.result.binding_locals.get(b) {
Some(it) => Ok(*it),
None => {
@@ -1922,7 +1931,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
}
- fn const_eval_discriminant(&self, variant: EnumVariantId) -> Result<i128> {
+ fn const_eval_discriminant(&self, variant: EnumVariantId) -> Result<'db, i128> {
let r = self.db.const_eval_discriminant(variant);
match r {
Ok(r) => Ok(r),
@@ -1993,7 +2002,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
&mut self,
mut current: BasicBlockId,
span: MirSpan,
- ) -> Result<BasicBlockId> {
+ ) -> Result<'db, BasicBlockId> {
current = self.pop_drop_scope_internal(current, span);
if !self.drop_scopes.is_empty() {
implementation_error!("Mismatched count between drop scope push and pops");
@@ -2021,9 +2030,14 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
}
-fn cast_kind(db: &dyn HirDatabase, source_ty: &Ty, target_ty: &Ty) -> Result<CastKind> {
- let from = CastTy::from_ty(db, source_ty);
- let cast = CastTy::from_ty(db, target_ty);
+fn cast_kind<'db>(
+ db: &'db dyn HirDatabase,
+ source_ty: &Ty,
+ target_ty: &Ty,
+) -> Result<'db, CastKind> {
+ let interner = DbInterner::new_with(db, None, None);
+ let from = CastTy::from_ty(db, source_ty.to_nextsolver(interner));
+ let cast = CastTy::from_ty(db, target_ty.to_nextsolver(interner));
Ok(match (from, cast) {
(Some(CastTy::Ptr(..) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
CastKind::PointerExposeAddress
@@ -2039,31 +2053,34 @@ fn cast_kind(db: &dyn HirDatabase, source_ty: &Ty, target_ty: &Ty) -> Result<Cas
})
}
-pub fn mir_body_for_closure_query(
- db: &dyn HirDatabase,
+pub fn mir_body_for_closure_query<'db>(
+ db: &'db dyn HirDatabase,
closure: InternedClosureId,
-) -> Result<Arc<MirBody>> {
+) -> Result<'db, Arc<MirBody>> {
let InternedClosure(owner, expr) = db.lookup_intern_closure(closure);
let body = db.body(owner);
let infer = db.infer(owner);
let Expr::Closure { args, body: root, .. } = &body[expr] else {
implementation_error!("closure expression is not closure");
};
- let TyKind::Closure(_, substs) = &infer[expr].kind(Interner) else {
+ let crate::next_solver::TyKind::Closure(_, substs) = infer[expr].kind() else {
implementation_error!("closure expression is not closure");
};
- let (captures, kind) = infer.closure_info(&closure.into());
+ let (captures, kind) = infer.closure_info(closure);
let mut ctx = MirLowerCtx::new(db, owner, &body, &infer);
+ let substs: &Substitution = &substs.to_chalk(ctx.interner);
// 0 is return local
- ctx.result.locals.alloc(Local { ty: infer[*root].clone() });
+ ctx.result.locals.alloc(Local { ty: infer[*root].to_chalk(ctx.interner) });
let closure_local = ctx.result.locals.alloc(Local {
ty: match kind {
- FnTrait::FnOnce | FnTrait::AsyncFnOnce => infer[expr].clone(),
+ FnTrait::FnOnce | FnTrait::AsyncFnOnce => infer[expr].to_chalk(ctx.interner),
FnTrait::FnMut | FnTrait::AsyncFnMut => {
- TyKind::Ref(Mutability::Mut, error_lifetime(), infer[expr].clone()).intern(Interner)
+ TyKind::Ref(Mutability::Mut, error_lifetime(), infer[expr].to_chalk(ctx.interner))
+ .intern(Interner)
}
FnTrait::Fn | FnTrait::AsyncFn => {
- TyKind::Ref(Mutability::Not, error_lifetime(), infer[expr].clone()).intern(Interner)
+ TyKind::Ref(Mutability::Not, error_lifetime(), infer[expr].to_chalk(ctx.interner))
+ .intern(Interner)
}
},
});
@@ -2082,7 +2099,7 @@ pub fn mir_body_for_closure_query(
let current = ctx.pop_drop_scope_assert_finished(current, root.into())?;
ctx.set_terminator(current, TerminatorKind::Return, (*root).into());
}
- let mut upvar_map: FxHashMap<LocalId, Vec<(&CapturedItem, usize)>> = FxHashMap::default();
+ let mut upvar_map: FxHashMap<LocalId, Vec<(&CapturedItem<'_>, usize)>> = FxHashMap::default();
for (i, capture) in captures.iter().enumerate() {
let local = ctx.binding_local(capture.place.local)?;
upvar_map.entry(local).or_default().push((capture, i));
@@ -2144,7 +2161,10 @@ pub fn mir_body_for_closure_query(
Ok(Arc::new(ctx.result))
}
-pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<MirBody>> {
+pub fn mir_body_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: DefWithBodyId,
+) -> Result<'db, Arc<MirBody>> {
let krate = def.krate(db);
let edition = krate.data(db).edition;
let detail = match def {
@@ -2177,22 +2197,22 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi
Ok(Arc::new(result))
}
-pub(crate) fn mir_body_cycle_result(
- _db: &dyn HirDatabase,
+pub(crate) fn mir_body_cycle_result<'db>(
+ _db: &'db dyn HirDatabase,
_def: DefWithBodyId,
-) -> Result<Arc<MirBody>> {
+) -> Result<'db, Arc<MirBody>> {
Err(MirLowerError::Loop)
}
-pub fn lower_to_mir(
- db: &dyn HirDatabase,
+pub fn lower_to_mir<'db>(
+ db: &'db dyn HirDatabase,
owner: DefWithBodyId,
body: &Body,
- infer: &InferenceResult,
+ infer: &InferenceResult<'db>,
// FIXME: root_expr should always be the body.body_expr, but since `X` in `[(); X]` doesn't have its own specific body yet, we
// need to take this input explicitly.
root_expr: ExprId,
-) -> Result<MirBody> {
+) -> Result<'db, MirBody> {
if infer.type_mismatches().next().is_some() || infer.is_erroneous() {
return Err(MirLowerError::HasErrors);
}
diff --git a/crates/hir-ty/src/mir/lower/as_place.rs b/crates/hir-ty/src/mir/lower/as_place.rs
index 42a1466462..bd7b644618 100644
--- a/crates/hir-ty/src/mir/lower/as_place.rs
+++ b/crates/hir-ty/src/mir/lower/as_place.rs
@@ -12,12 +12,12 @@ macro_rules! not_supported {
};
}
-impl MirLowerCtx<'_> {
+impl<'db> MirLowerCtx<'_, 'db> {
fn lower_expr_to_some_place_without_adjust(
&mut self,
expr_id: ExprId,
prev_block: BasicBlockId,
- ) -> Result<Option<(Place, BasicBlockId)>> {
+ ) -> Result<'db, Option<(Place, BasicBlockId)>> {
let ty = self.expr_ty_without_adjust(expr_id);
let place = self.temp(ty, prev_block, expr_id.into())?;
let Some(current) =
@@ -32,11 +32,11 @@ impl MirLowerCtx<'_> {
&mut self,
expr_id: ExprId,
prev_block: BasicBlockId,
- adjustments: &[Adjustment],
- ) -> Result<Option<(Place, BasicBlockId)>> {
+ adjustments: &[Adjustment<'db>],
+ ) -> Result<'db, Option<(Place, BasicBlockId)>> {
let ty = adjustments
.last()
- .map(|it| it.target.clone())
+ .map(|it| it.target.to_chalk(self.interner))
.unwrap_or_else(|| self.expr_ty_without_adjust(expr_id));
let place = self.temp(ty, prev_block, expr_id.into())?;
let Some(current) =
@@ -52,9 +52,9 @@ impl MirLowerCtx<'_> {
current: BasicBlockId,
expr_id: ExprId,
upgrade_rvalue: bool,
- adjustments: &[Adjustment],
- ) -> Result<Option<(Place, BasicBlockId)>> {
- let try_rvalue = |this: &mut MirLowerCtx<'_>| {
+ adjustments: &[Adjustment<'db>],
+ ) -> Result<'db, Option<(Place, BasicBlockId)>> {
+ let try_rvalue = |this: &mut MirLowerCtx<'_, 'db>| {
if !upgrade_rvalue {
return Err(MirLowerError::MutatingRvalue);
}
@@ -89,11 +89,11 @@ impl MirLowerCtx<'_> {
current,
r,
rest.last()
- .map(|it| it.target.clone())
+ .map(|it| it.target.to_chalk(self.interner))
.unwrap_or_else(|| self.expr_ty_without_adjust(expr_id)),
- last.target.clone(),
+ last.target.to_chalk(self.interner),
expr_id.into(),
- match od.0 {
+ match od.0.to_chalk(self.interner) {
Some(Mutability::Mut) => true,
Some(Mutability::Not) => false,
None => {
@@ -114,7 +114,7 @@ impl MirLowerCtx<'_> {
current: BasicBlockId,
expr_id: ExprId,
upgrade_rvalue: bool,
- ) -> Result<Option<(Place, BasicBlockId)>> {
+ ) -> Result<'db, Option<(Place, BasicBlockId)>> {
match self.infer.expr_adjustments.get(&expr_id) {
Some(a) => self.lower_expr_as_place_with_adjust(current, expr_id, upgrade_rvalue, a),
None => self.lower_expr_as_place_without_adjust(current, expr_id, upgrade_rvalue),
@@ -126,8 +126,8 @@ impl MirLowerCtx<'_> {
current: BasicBlockId,
expr_id: ExprId,
upgrade_rvalue: bool,
- ) -> Result<Option<(Place, BasicBlockId)>> {
- let try_rvalue = |this: &mut MirLowerCtx<'_>| {
+ ) -> Result<'db, Option<(Place, BasicBlockId)>> {
+ let try_rvalue = |this: &mut MirLowerCtx<'_, 'db>| {
if !upgrade_rvalue {
return Err(MirLowerError::MutatingRvalue);
}
@@ -230,6 +230,7 @@ impl MirLowerCtx<'_> {
"[overloaded index]".to_owned(),
));
};
+ let index_fn = (index_fn.0, index_fn.1.to_chalk(self.interner));
let Some((base_place, current)) =
self.lower_expr_as_place(current, *base, true)?
else {
@@ -285,7 +286,7 @@ impl MirLowerCtx<'_> {
index_operand: Operand,
span: MirSpan,
index_fn: (FunctionId, Substitution),
- ) -> Result<Option<(Place, BasicBlockId)>> {
+ ) -> Result<'db, Option<(Place, BasicBlockId)>> {
let mutability = match base_ty.as_reference() {
Some((_, _, mutability)) => mutability,
None => Mutability::Not,
@@ -319,7 +320,7 @@ impl MirLowerCtx<'_> {
target_ty: Ty,
span: MirSpan,
mutability: bool,
- ) -> Result<Option<(Place, BasicBlockId)>> {
+ ) -> Result<'db, Option<(Place, BasicBlockId)>> {
let (chalk_mut, trait_lang_item, trait_method_name, borrow_kind) = if !mutability {
(
Mutability::Not,
diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 0440d85022..359c4fbb2e 100644
--- a/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -2,16 +2,17 @@
use hir_def::{AssocItemId, hir::ExprId, signatures::VariantFields};
+use crate::next_solver::mapping::NextSolverToChalk;
use crate::{
BindingMode,
mir::{
LocalId, MutBorrowKind, Operand, OperandKind,
lower::{
BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, Interner,
- MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Pat, PatId, Place,
- PlaceElem, ProjectionElem, RecordFieldPat, ResolveValueResult, Result, Rvalue,
- Substitution, SwitchTargets, TerminatorKind, TupleFieldId, TupleId, TyBuilder, TyKind,
- ValueNs, VariantId,
+ MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Pat, PatId, Place, PlaceElem,
+ ProjectionElem, RecordFieldPat, ResolveValueResult, Result, Rvalue, Substitution,
+ SwitchTargets, TerminatorKind, TupleFieldId, TupleId, TyBuilder, TyKind, ValueNs,
+ VariantId,
},
},
};
@@ -50,7 +51,7 @@ enum MatchingMode {
Assign,
}
-impl MirLowerCtx<'_> {
+impl<'db> MirLowerCtx<'_, 'db> {
/// It gets a `current` unterminated block, appends some statements and possibly a terminator to it to check if
/// the pattern matches and write bindings, and returns two unterminated blocks, one for the matched path (which
/// can be the `current` block) and one for the mismatched path. If the input pattern is irrefutable, the
@@ -66,7 +67,7 @@ impl MirLowerCtx<'_> {
current_else: Option<BasicBlockId>,
cond_place: Place,
pattern: PatId,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
let (current, current_else) = self.pattern_match_inner(
current,
current_else,
@@ -89,7 +90,7 @@ impl MirLowerCtx<'_> {
current: BasicBlockId,
value: Place,
pattern: PatId,
- ) -> Result<BasicBlockId> {
+ ) -> Result<'db, BasicBlockId> {
let (current, _) =
self.pattern_match_inner(current, None, value, pattern, MatchingMode::Assign)?;
Ok(current)
@@ -100,7 +101,7 @@ impl MirLowerCtx<'_> {
id: BindingId,
current: BasicBlockId,
local: LocalId,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
self.pattern_match_binding(
id,
BindingMode::Move,
@@ -118,7 +119,7 @@ impl MirLowerCtx<'_> {
mut cond_place: Place,
pattern: PatId,
mode: MatchingMode,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
let cnt = self.infer.pat_adjustments.get(&pattern).map(|x| x.len()).unwrap_or_default();
cond_place.projection = self.result.projection_store.intern(
cond_place
@@ -134,8 +135,8 @@ impl MirLowerCtx<'_> {
Pat::Missing => return Err(MirLowerError::IncompletePattern),
Pat::Wild => (current, current_else),
Pat::Tuple { args, ellipsis } => {
- let subst = match self.infer[pattern].kind(Interner) {
- TyKind::Tuple(_, s) => s,
+ let subst = match self.infer[pattern].to_chalk(self.interner).kind(Interner) {
+ TyKind::Tuple(_, s) => s.clone(),
_ => {
return Err(MirLowerError::TypeError(
"non tuple type matched with tuple pattern",
@@ -207,9 +208,11 @@ impl MirLowerCtx<'_> {
)?
}
Pat::Range { start, end } => {
- let mut add_check = |l: &ExprId, binop| -> Result<()> {
- let lv =
- self.lower_literal_or_const_to_operand(self.infer[pattern].clone(), l)?;
+ let mut add_check = |l: &ExprId, binop| -> Result<'db, ()> {
+ let lv = self.lower_literal_or_const_to_operand(
+ self.infer[pattern].to_chalk(self.interner),
+ l,
+ )?;
let else_target = *current_else.get_or_insert_with(|| self.new_basic_block());
let next = self.new_basic_block();
let discr: Place =
@@ -249,7 +252,9 @@ impl MirLowerCtx<'_> {
Pat::Slice { prefix, slice, suffix } => {
if mode == MatchingMode::Check {
// emit runtime length check for slice
- if let TyKind::Slice(_) = self.infer[pattern].kind(Interner) {
+ if let TyKind::Slice(_) =
+ self.infer[pattern].to_chalk(self.interner).kind(Interner)
+ {
let pattern_len = prefix.len() + suffix.len();
let place_len: Place =
self.temp(TyBuilder::usize(), current, pattern.into())?.into();
@@ -393,15 +398,16 @@ impl MirLowerCtx<'_> {
if let Some(x) = self.infer.assoc_resolutions_for_pat(pattern)
&& let AssocItemId::ConstId(c) = x.0
{
- break 'b (c, x.1);
+ break 'b (c, x.1.to_chalk(self.interner));
}
if let ResolveValueResult::ValueNs(ValueNs::ConstId(c), _) = pr {
break 'b (c, Substitution::empty(Interner));
}
not_supported!("path in pattern position that is not const or variant")
};
- let tmp: Place =
- self.temp(self.infer[pattern].clone(), current, pattern.into())?.into();
+ let tmp: Place = self
+ .temp(self.infer[pattern].to_chalk(self.interner), current, pattern.into())?
+ .into();
let span = pattern.into();
self.lower_const(
c.into(),
@@ -409,7 +415,7 @@ impl MirLowerCtx<'_> {
tmp,
subst,
span,
- self.infer[pattern].clone(),
+ self.infer[pattern].to_chalk(self.interner),
)?;
let tmp2: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into();
self.push_assignment(
@@ -438,7 +444,10 @@ impl MirLowerCtx<'_> {
Pat::Lit(l) => match &self.body[*l] {
Expr::Literal(l) => {
if mode == MatchingMode::Check {
- let c = self.lower_literal_to_operand(self.infer[pattern].clone(), l)?;
+ let c = self.lower_literal_to_operand(
+ self.infer[pattern].to_chalk(self.interner),
+ l,
+ )?;
self.pattern_match_const(current_else, current, c, cond_place, pattern)?
} else {
(current, current_else)
@@ -514,7 +523,7 @@ impl MirLowerCtx<'_> {
span: MirSpan,
current: BasicBlockId,
current_else: Option<BasicBlockId>,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
let target_place = self.binding_local(id)?;
self.push_storage_live(id, current)?;
self.push_match_assignment(current, target_place, mode, cond_place, span);
@@ -536,8 +545,10 @@ impl MirLowerCtx<'_> {
BindingMode::Move => {
Operand { kind: OperandKind::Copy(cond_place), span: None }.into()
}
- BindingMode::Ref(Mutability::Not) => Rvalue::Ref(BorrowKind::Shared, cond_place),
- BindingMode::Ref(Mutability::Mut) => {
+ BindingMode::Ref(rustc_ast_ir::Mutability::Not) => {
+ Rvalue::Ref(BorrowKind::Shared, cond_place)
+ }
+ BindingMode::Ref(rustc_ast_ir::Mutability::Mut) => {
Rvalue::Ref(BorrowKind::Mut { kind: MutBorrowKind::Default }, cond_place)
}
},
@@ -552,7 +563,7 @@ impl MirLowerCtx<'_> {
c: Operand,
cond_place: Place,
pattern: Idx<Pat>,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
let then_target = self.new_basic_block();
let else_target = current_else.unwrap_or_else(|| self.new_basic_block());
let discr: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into();
@@ -587,7 +598,7 @@ impl MirLowerCtx<'_> {
mut current_else: Option<BasicBlockId>,
shape: AdtPatternShape<'_>,
mode: MatchingMode,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
Ok(match variant {
VariantId::EnumVariantId(v) => {
if mode == MatchingMode::Check {
@@ -640,7 +651,7 @@ impl MirLowerCtx<'_> {
current_else: Option<BasicBlockId>,
cond_place: &Place,
mode: MatchingMode,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
Ok(match shape {
AdtPatternShape::Record { args } => {
let it = args
@@ -656,7 +667,7 @@ impl MirLowerCtx<'_> {
x.pat,
))
})
- .collect::<Result<Vec<_>>>()?;
+ .collect::<Result<'db, Vec<_>>>()?;
self.pattern_match_adt(current, current_else, it.into_iter(), cond_place, mode)?
}
AdtPatternShape::Tuple { args, ellipsis } => {
@@ -684,7 +695,7 @@ impl MirLowerCtx<'_> {
args: impl Iterator<Item = (PlaceElem, PatId)>,
cond_place: &Place,
mode: MatchingMode,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
for (proj, arg) in args {
let cond_place = cond_place.project(proj, &mut self.result.projection_store);
(current, current_else) =
@@ -702,7 +713,7 @@ impl MirLowerCtx<'_> {
fields: impl DoubleEndedIterator<Item = PlaceElem> + Clone,
cond_place: &Place,
mode: MatchingMode,
- ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
+ ) -> Result<'db, (BasicBlockId, Option<BasicBlockId>)> {
let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
let it = al
.iter()
diff --git a/crates/hir-ty/src/mir/lower/tests.rs b/crates/hir-ty/src/mir/lower/tests.rs
index 1d7a16ed72..bac694eabb 100644
--- a/crates/hir-ty/src/mir/lower/tests.rs
+++ b/crates/hir-ty/src/mir/lower/tests.rs
@@ -4,16 +4,11 @@ use span::Edition;
use test_fixture::WithFixture;
use triomphe::Arc;
-use crate::{
- db::HirDatabase,
- mir::{MirBody, MirLowerError},
- setup_tracing,
- test_db::TestDB,
-};
+use crate::{db::HirDatabase, mir::MirBody, setup_tracing, test_db::TestDB};
fn lower_mir(
#[rust_analyzer::rust_fixture] ra_fixture: &str,
-) -> FxHashMap<String, Result<Arc<MirBody>, MirLowerError>> {
+) -> FxHashMap<String, Result<Arc<MirBody>, ()>> {
let _tracing = setup_tracing();
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
let file_id = *file_ids.last().unwrap();
@@ -28,7 +23,7 @@ fn lower_mir(
.map(|func| {
let name = db.function_signature(func).name.display(&db, Edition::CURRENT).to_string();
let mir = db.mir_body(func.into());
- (name, mir)
+ (name, mir.map_err(drop))
})
.collect()
}
diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs
index f293f38c76..4bc81a4806 100644
--- a/crates/hir-ty/src/mir/monomorphization.rs
+++ b/crates/hir-ty/src/mir/monomorphization.rs
@@ -16,6 +16,8 @@ use chalk_ir::{
use hir_def::DefWithBodyId;
use triomphe::Arc;
+use crate::next_solver::DbInterner;
+use crate::next_solver::mapping::{ChalkToNextSolver, NextSolverToChalk};
use crate::{
Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind,
consteval::{intern_const_scalar, unknown_const},
@@ -33,14 +35,15 @@ macro_rules! not_supported {
};
}
-struct Filler<'a> {
- db: &'a dyn HirDatabase,
- trait_env: Arc<TraitEnvironment<'a>>,
+struct Filler<'a, 'db> {
+ db: &'db dyn HirDatabase,
+ trait_env: Arc<TraitEnvironment<'db>>,
subst: &'a Substitution,
generics: Option<Generics>,
+ interner: DbInterner<'db>,
}
-impl FallibleTypeFolder<Interner> for Filler<'_> {
- type Error = MirLowerError;
+impl<'a, 'db> FallibleTypeFolder<Interner> for Filler<'a, 'db> {
+ type Error = MirLowerError<'db>;
fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> {
self
@@ -80,8 +83,13 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
trait_env: self.trait_env.clone(),
subst: &subst,
generics: Some(generics(self.db, func.into())),
+ interner: self.interner,
};
- filler.try_fold_ty(infer.type_of_rpit[idx].clone(), outer_binder)
+ filler.try_fold_ty(
+ infer.type_of_rpit[idx.to_nextsolver(self.interner)]
+ .to_chalk(self.interner),
+ outer_binder,
+ )
}
crate::ImplTraitId::TypeAliasImplTrait(..) => {
not_supported!("type alias impl trait");
@@ -148,8 +156,8 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
}
}
-impl Filler<'_> {
- fn fill_ty(&mut self, ty: &mut Ty) -> Result<(), MirLowerError> {
+impl<'a, 'db> Filler<'a, 'db> {
+ fn fill_ty(&mut self, ty: &mut Ty) -> Result<(), MirLowerError<'db>> {
let tmp = mem::replace(ty, TyKind::Error.intern(Interner));
*ty = normalize(
self.db,
@@ -159,19 +167,19 @@ impl Filler<'_> {
Ok(())
}
- fn fill_const(&mut self, c: &mut Const) -> Result<(), MirLowerError> {
+ fn fill_const(&mut self, c: &mut Const) -> Result<(), MirLowerError<'db>> {
let tmp = mem::replace(c, unknown_const(c.data(Interner).ty.clone()));
*c = tmp.try_fold_with(self, DebruijnIndex::INNERMOST)?;
Ok(())
}
- fn fill_subst(&mut self, ty: &mut Substitution) -> Result<(), MirLowerError> {
+ fn fill_subst(&mut self, ty: &mut Substitution) -> Result<(), MirLowerError<'db>> {
let tmp = mem::replace(ty, Substitution::empty(Interner));
*ty = tmp.try_fold_with(self, DebruijnIndex::INNERMOST)?;
Ok(())
}
- fn fill_operand(&mut self, op: &mut Operand) -> Result<(), MirLowerError> {
+ fn fill_operand(&mut self, op: &mut Operand) -> Result<(), MirLowerError<'db>> {
match &mut op.kind {
OperandKind::Constant(c) => {
match &c.data(Interner).value {
@@ -222,7 +230,7 @@ impl Filler<'_> {
Ok(())
}
- fn fill_body(&mut self, body: &mut MirBody) -> Result<(), MirLowerError> {
+ fn fill_body(&mut self, body: &mut MirBody) -> Result<(), MirLowerError<'db>> {
for (_, l) in body.locals.iter_mut() {
self.fill_ty(&mut l.ty)?;
}
@@ -306,9 +314,10 @@ pub fn monomorphized_mir_body_query<'db>(
owner: DefWithBodyId,
subst: Substitution,
trait_env: Arc<crate::TraitEnvironment<'db>>,
-) -> Result<Arc<MirBody>, MirLowerError> {
+) -> Result<Arc<MirBody>, MirLowerError<'db>> {
let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def));
- let filler = &mut Filler { db, subst: &subst, trait_env, generics };
+ let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block);
+ let filler = &mut Filler { db, subst: &subst, trait_env, generics, interner };
let body = db.mir_body(owner)?;
let mut body = (*body).clone();
filler.fill_body(&mut body)?;
@@ -320,7 +329,7 @@ pub(crate) fn monomorphized_mir_body_cycle_result<'db>(
_: DefWithBodyId,
_: Substitution,
_: Arc<crate::TraitEnvironment<'db>>,
-) -> Result<Arc<MirBody>, MirLowerError> {
+) -> Result<Arc<MirBody>, MirLowerError<'db>> {
Err(MirLowerError::Loop)
}
@@ -329,10 +338,11 @@ pub fn monomorphized_mir_body_for_closure_query<'db>(
closure: InternedClosureId,
subst: Substitution,
trait_env: Arc<crate::TraitEnvironment<'db>>,
-) -> Result<Arc<MirBody>, MirLowerError> {
+) -> Result<Arc<MirBody>, MirLowerError<'db>> {
let InternedClosure(owner, _) = db.lookup_intern_closure(closure);
let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def));
- let filler = &mut Filler { db, subst: &subst, trait_env, generics };
+ let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block);
+ let filler = &mut Filler { db, subst: &subst, trait_env, generics, interner };
let body = db.mir_body_for_closure(closure)?;
let mut body = (*body).clone();
filler.fill_body(&mut body)?;
diff --git a/crates/hir-ty/src/next_solver.rs b/crates/hir-ty/src/next_solver.rs
index ab167e88af..776e0d956f 100644
--- a/crates/hir-ty/src/next_solver.rs
+++ b/crates/hir-ty/src/next_solver.rs
@@ -33,6 +33,9 @@ pub use region::*;
pub use solver::*;
pub use ty::*;
+pub use crate::lower_nextsolver::ImplTraitIdx;
+pub use rustc_ast_ir::Mutability;
+
pub type Binder<'db, T> = rustc_type_ir::Binder<DbInterner<'db>, T>;
pub type EarlyBinder<'db, T> = rustc_type_ir::EarlyBinder<DbInterner<'db>, T>;
pub type Canonical<'db, T> = rustc_type_ir::Canonical<DbInterner<'db>, T>;
diff --git a/crates/hir-ty/src/next_solver/def_id.rs b/crates/hir-ty/src/next_solver/def_id.rs
index 1ae59beca2..918a311ea9 100644
--- a/crates/hir-ty/src/next_solver/def_id.rs
+++ b/crates/hir-ty/src/next_solver/def_id.rs
@@ -139,6 +139,17 @@ impl TryFrom<SolverDefId> for GenericDefId {
}
}
+impl SolverDefId {
+ #[inline]
+ #[track_caller]
+ pub fn expect_opaque_ty(self) -> InternedOpaqueTyId {
+ match self {
+ SolverDefId::InternedOpaqueTyId(it) => it,
+ _ => panic!("expected opaque type, found {self:?}"),
+ }
+ }
+}
+
impl<'db> inherent::DefId<DbInterner<'db>> for SolverDefId {
fn as_local(self) -> Option<SolverDefId> {
Some(self)
diff --git a/crates/hir-ty/src/next_solver/fold.rs b/crates/hir-ty/src/next_solver/fold.rs
index 405a57d9e8..a42fdb0943 100644
--- a/crates/hir-ty/src/next_solver/fold.rs
+++ b/crates/hir-ty/src/next_solver/fold.rs
@@ -129,3 +129,26 @@ where
if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
}
}
+
+pub fn fold_tys<'db, T: TypeFoldable<DbInterner<'db>>>(
+ interner: DbInterner<'db>,
+ t: T,
+ callback: impl FnMut(Ty<'db>) -> Ty<'db>,
+) -> T {
+ struct Folder<'db, F> {
+ interner: DbInterner<'db>,
+ callback: F,
+ }
+ impl<'db, F: FnMut(Ty<'db>) -> Ty<'db>> TypeFolder<DbInterner<'db>> for Folder<'db, F> {
+ fn cx(&self) -> DbInterner<'db> {
+ self.interner
+ }
+
+ fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
+ let t = t.super_fold_with(self);
+ (self.callback)(t)
+ }
+ }
+
+ t.fold_with(&mut Folder { interner, callback })
+}
diff --git a/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs
index 097bb85cbd..89a4d9202a 100644
--- a/crates/hir-ty/src/next_solver/generic_arg.rs
+++ b/crates/hir-ty/src/next_solver/generic_arg.rs
@@ -1,7 +1,8 @@
//! Things related to generic args in the next-trait-solver.
-use hir_def::GenericParamId;
+use hir_def::{GenericDefId, GenericParamId};
use intern::{Interned, Symbol};
+use rustc_type_ir::inherent::Const as _;
use rustc_type_ir::{
ClosureArgs, CollectAndApply, ConstVid, CoroutineArgs, CoroutineClosureArgs, FnSig, FnSigTys,
GenericArgKind, IntTy, Interner, TermKind, TyKind, TyVid, TypeFoldable, TypeVisitable,
@@ -216,6 +217,59 @@ impl<'db> GenericArgs<'db> {
interner.mk_args(&args)
}
+ /// Like `for_item`, but prefers the default of a parameter if it has any.
+ pub fn for_item_with_defaults<F>(
+ interner: DbInterner<'db>,
+ def_id: GenericDefId,
+ mut fallback: F,
+ ) -> GenericArgs<'db>
+ where
+ F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
+ {
+ let defaults = interner.db.generic_defaults_ns(def_id);
+ Self::for_item(interner, def_id.into(), |name, idx, id, prev| {
+ match defaults.get(idx as usize) {
+ Some(default) => default.instantiate(interner, prev),
+ None => fallback(name, idx, id, prev),
+ }
+ })
+ }
+
+ /// Like `for_item()`, but calls first uses the args from `first`.
+ pub fn fill_rest<F>(
+ interner: DbInterner<'db>,
+ def_id: SolverDefId,
+ first: impl IntoIterator<Item = GenericArg<'db>>,
+ mut fallback: F,
+ ) -> GenericArgs<'db>
+ where
+ F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
+ {
+ let mut iter = first.into_iter();
+ Self::for_item(interner, def_id, |name, idx, id, prev| {
+ iter.next().unwrap_or_else(|| fallback(name, idx, id, prev))
+ })
+ }
+
+ /// Appends default param values to `first` if needed. Params without default will call `fallback()`.
+ pub fn fill_with_defaults<F>(
+ interner: DbInterner<'db>,
+ def_id: GenericDefId,
+ first: impl IntoIterator<Item = GenericArg<'db>>,
+ mut fallback: F,
+ ) -> GenericArgs<'db>
+ where
+ F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
+ {
+ let defaults = interner.db.generic_defaults_ns(def_id);
+ Self::fill_rest(interner, def_id.into(), first, |name, idx, id, prev| {
+ defaults
+ .get(idx as usize)
+ .map(|default| default.instantiate(interner, prev))
+ .unwrap_or_else(|| fallback(name, idx, id, prev))
+ })
+ }
+
fn fill_item<F>(
args: &mut SmallVec<[GenericArg<'db>; 8]>,
interner: DbInterner<'_>,
@@ -271,6 +325,18 @@ impl<'db> GenericArgs<'db> {
}
}
}
+
+ pub fn types(self) -> impl Iterator<Item = Ty<'db>> {
+ self.iter().filter_map(|it| it.as_type())
+ }
+
+ pub fn consts(self) -> impl Iterator<Item = Const<'db>> {
+ self.iter().filter_map(|it| it.as_const())
+ }
+
+ pub fn regions(self) -> impl Iterator<Item = Region<'db>> {
+ self.iter().filter_map(|it| it.as_region())
+ }
}
impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for GenericArgs<'db> {
diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index 8e922abacb..1bb6934e07 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -10,6 +10,7 @@ pub use at::DefineOpaqueTypes;
use ena::undo_log::UndoLogs;
use ena::unify as ut;
use hir_def::GenericParamId;
+use hir_def::lang_item::LangItem;
use intern::Symbol;
use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage};
use region_constraints::{
@@ -18,6 +19,7 @@ use region_constraints::{
pub use relate::StructurallyRelateAliases;
pub use relate::combine::PredicateEmittingRelation;
use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
use rustc_pattern_analysis::Captures;
use rustc_type_ir::error::{ExpectedFound, TypeError};
use rustc_type_ir::inherent::{
@@ -38,7 +40,10 @@ use unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
use crate::next_solver::fold::BoundVarReplacerDelegate;
use crate::next_solver::infer::opaque_types::table::OpaqueTypeStorageEntries;
-use crate::next_solver::{BoundConst, BoundRegion, BoundTy, BoundVarKind};
+use crate::next_solver::infer::select::EvaluationResult;
+use crate::next_solver::infer::traits::PredicateObligation;
+use crate::next_solver::obligation_ctxt::ObligationCtxt;
+use crate::next_solver::{BoundConst, BoundRegion, BoundTy, BoundVarKind, Goal, SolverContext};
use super::generics::GenericParamDef;
use super::{
@@ -62,7 +67,7 @@ pub(crate) mod traits;
mod type_variable;
mod unify_key;
-/// `InferOk<'tcx, ()>` is used a lot. It may seem like a useless wrapper
+/// `InferOk<'db, ()>` is used a lot. It may seem like a useless wrapper
/// around `PredicateObligations`, but it has one important property:
/// because `InferOk` is marked with `#[must_use]`, if you have a method
/// `InferCtxt::f` that returns `InferResult<()>` and you call it with
@@ -395,6 +400,102 @@ impl<'db> InferCtxt<'db> {
self.typing_mode
}
+ /// See the comment on [OpaqueTypesJank](crate::solve::OpaqueTypesJank)
+ /// for more details.
+ pub fn predicate_may_hold_opaque_types_jank(
+ &self,
+ obligation: &PredicateObligation<'db>,
+ ) -> bool {
+ <&SolverContext<'db>>::from(self).root_goal_may_hold_opaque_types_jank(Goal::new(
+ self.interner,
+ obligation.param_env,
+ obligation.predicate,
+ ))
+ }
+
+ /// Evaluates whether the predicate can be satisfied in the given
+ /// `ParamEnv`, and returns `false` if not certain. However, this is
+ /// not entirely accurate if inference variables are involved.
+ ///
+ /// This version may conservatively fail when outlives obligations
+ /// are required. Therefore, this version should only be used for
+ /// optimizations or diagnostics and be treated as if it can always
+ /// return `false`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # #![allow(dead_code)]
+ /// trait Trait {}
+ ///
+ /// fn check<T: Trait>() {}
+ ///
+ /// fn foo<T: 'static>()
+ /// where
+ /// &'static T: Trait,
+ /// {
+ /// // Evaluating `&'?0 T: Trait` adds a `'?0: 'static` outlives obligation,
+ /// // which means that `predicate_must_hold_considering_regions` will return
+ /// // `false`.
+ /// check::<&'_ T>();
+ /// }
+ /// ```
+ fn predicate_must_hold_considering_regions(
+ &self,
+ obligation: &PredicateObligation<'db>,
+ ) -> bool {
+ self.evaluate_obligation(obligation).must_apply_considering_regions()
+ }
+
+ /// Evaluates whether the predicate can be satisfied in the given
+ /// `ParamEnv`, and returns `false` if not certain. However, this is
+ /// not entirely accurate if inference variables are involved.
+ ///
+ /// This version ignores all outlives constraints.
+ fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'db>) -> bool {
+ self.evaluate_obligation(obligation).must_apply_modulo_regions()
+ }
+
+ /// Evaluate a given predicate, capturing overflow and propagating it back.
+ fn evaluate_obligation(&self, obligation: &PredicateObligation<'db>) -> EvaluationResult {
+ let param_env = obligation.param_env;
+
+ self.probe(|snapshot| {
+ let mut ocx = ObligationCtxt::new(self);
+ ocx.register_obligation(obligation.clone());
+ let mut result = EvaluationResult::EvaluatedToOk;
+ for error in ocx.select_all_or_error() {
+ if error.is_true_error() {
+ return EvaluationResult::EvaluatedToErr;
+ } else {
+ result = result.max(EvaluationResult::EvaluatedToAmbig);
+ }
+ }
+ if self.opaque_types_added_in_snapshot(snapshot) {
+ result = result.max(EvaluationResult::EvaluatedToOkModuloOpaqueTypes);
+ } else if self.region_constraints_added_in_snapshot(snapshot) {
+ result = result.max(EvaluationResult::EvaluatedToOkModuloRegions);
+ }
+ result
+ })
+ }
+
+ pub fn type_is_copy_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool {
+ let ty = self.resolve_vars_if_possible(ty);
+
+ let Some(copy_def_id) =
+ LangItem::Copy.resolve_trait(self.interner.db, self.interner.krate.unwrap())
+ else {
+ return false;
+ };
+
+ // This can get called from typeck (by euv), and `moves_by_default`
+ // rightly refuses to work with inference variables, but
+ // moves_by_default has a cache, which we want to use in other
+ // cases.
+ traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
+ }
+
pub fn unresolved_variables(&self) -> Vec<Ty<'db>> {
let mut inner = self.inner.borrow_mut();
let mut vars: Vec<Ty<'db>> = inner
@@ -682,6 +783,17 @@ impl<'db> InferCtxt<'db> {
})
}
+ /// Like `fresh_args_for_item()`, but first uses the args from `first`.
+ pub fn fill_rest_fresh_args(
+ &self,
+ def_id: SolverDefId,
+ first: impl IntoIterator<Item = GenericArg<'db>>,
+ ) -> GenericArgs<'db> {
+ GenericArgs::fill_rest(self.interner, def_id, first, |name, index, kind, _| {
+ self.var_for_def(kind, name)
+ })
+ }
+
/// Returns `true` if errors have been reported since this infcx was
/// created. This is sometimes used as a heuristic to skip
/// reporting errors that often occur as a result of earlier
diff --git a/crates/hir-ty/src/next_solver/infer/resolve.rs b/crates/hir-ty/src/next_solver/infer/resolve.rs
index 84338ade6e..4bd3fbd498 100644
--- a/crates/hir-ty/src/next_solver/infer/resolve.rs
+++ b/crates/hir-ty/src/next_solver/infer/resolve.rs
@@ -2,11 +2,12 @@
use rustc_type_ir::{
ConstKind, FallibleTypeFolder, InferConst, InferTy, RegionKind, TyKind, TypeFoldable,
- TypeFolder, TypeSuperFoldable, TypeVisitableExt, data_structures::DelayedMap,
- inherent::IntoKind,
+ TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+ data_structures::DelayedMap,
+ inherent::{Const as _, IntoKind, Ty as _},
};
-use crate::next_solver::{Const, DbInterner, Region, Ty};
+use crate::next_solver::{Const, DbInterner, ErrorGuaranteed, Region, Ty};
use super::{FixupError, FixupResult, InferCtxt};
@@ -60,3 +61,48 @@ impl<'a, 'db> TypeFolder<DbInterner<'db>> for OpportunisticVarResolver<'a, 'db>
}
}
}
+
+pub struct ReplaceInferWithError<'db> {
+ interner: DbInterner<'db>,
+}
+
+impl<'db> ReplaceInferWithError<'db> {
+ #[inline]
+ pub fn new(interner: DbInterner<'db>) -> Self {
+ Self { interner }
+ }
+}
+
+impl<'db> TypeFolder<DbInterner<'db>> for ReplaceInferWithError<'db> {
+ fn cx(&self) -> DbInterner<'db> {
+ self.interner
+ }
+
+ fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
+ if !t.has_infer() {
+ return t;
+ }
+
+ if t.is_infer() {
+ Ty::new_error(self.interner, ErrorGuaranteed)
+ } else {
+ t.super_fold_with(self)
+ }
+ }
+
+ fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
+ if !c.has_infer() {
+ return c;
+ }
+
+ if c.is_ct_infer() {
+ Const::new_error(self.interner, ErrorGuaranteed)
+ } else {
+ c.super_fold_with(self)
+ }
+ }
+
+ fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
+ if r.is_var() { Region::error(self.interner) } else { r }
+ }
+}
diff --git a/crates/hir-ty/src/next_solver/infer/select.rs b/crates/hir-ty/src/next_solver/infer/select.rs
index 4f111fa662..392e2b9329 100644
--- a/crates/hir-ty/src/next_solver/infer/select.rs
+++ b/crates/hir-ty/src/next_solver/infer/select.rs
@@ -12,6 +12,7 @@ use crate::{
Const, ErrorGuaranteed, GenericArgs, Goal, TraitRef, Ty, TypeError,
infer::{
InferCtxt,
+ select::EvaluationResult::*,
traits::{Obligation, ObligationCause, PredicateObligation, TraitObligation},
},
inspect::{InspectCandidate, InspectGoal, ProofTreeVisitor},
@@ -47,6 +48,83 @@ pub enum NotConstEvaluatable {
MentionsParam,
}
+/// The result of trait evaluation. The order is important
+/// here as the evaluation of a list is the maximum of the
+/// evaluations.
+///
+/// The evaluation results are ordered:
+/// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
+/// implies `EvaluatedToAmbig` implies `EvaluatedToAmbigStackDependent`
+/// - the "union" of evaluation results is equal to their maximum -
+/// all the "potential success" candidates can potentially succeed,
+/// so they are noops when unioned with a definite error, and within
+/// the categories it's easy to see that the unions are correct.
+#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
+pub enum EvaluationResult {
+ /// Evaluation successful.
+ EvaluatedToOk,
+ /// Evaluation successful, but there were unevaluated region obligations.
+ EvaluatedToOkModuloRegions,
+ /// Evaluation successful, but need to rerun because opaque types got
+ /// hidden types assigned without it being known whether the opaque types
+ /// are within their defining scope
+ EvaluatedToOkModuloOpaqueTypes,
+ /// Evaluation is known to be ambiguous -- it *might* hold for some
+ /// assignment of inference variables, but it might not.
+ ///
+ /// While this has the same meaning as `EvaluatedToAmbigStackDependent` -- we can't
+ /// know whether this obligation holds or not -- it is the result we
+ /// would get with an empty stack, and therefore is cacheable.
+ EvaluatedToAmbig,
+ /// Evaluation failed because of recursion involving inference
+ /// variables. We are somewhat imprecise there, so we don't actually
+ /// know the real result.
+ ///
+ /// This can't be trivially cached because the result depends on the
+ /// stack results.
+ EvaluatedToAmbigStackDependent,
+ /// Evaluation failed.
+ EvaluatedToErr,
+}
+
+impl EvaluationResult {
+ /// Returns `true` if this evaluation result is known to apply, even
+ /// considering outlives constraints.
+ pub fn must_apply_considering_regions(self) -> bool {
+ self == EvaluatedToOk
+ }
+
+ /// Returns `true` if this evaluation result is known to apply, ignoring
+ /// outlives constraints.
+ pub fn must_apply_modulo_regions(self) -> bool {
+ self <= EvaluatedToOkModuloRegions
+ }
+
+ pub fn may_apply(self) -> bool {
+ match self {
+ EvaluatedToOkModuloOpaqueTypes
+ | EvaluatedToOk
+ | EvaluatedToOkModuloRegions
+ | EvaluatedToAmbig
+ | EvaluatedToAmbigStackDependent => true,
+
+ EvaluatedToErr => false,
+ }
+ }
+
+ pub fn is_stack_dependent(self) -> bool {
+ match self {
+ EvaluatedToAmbigStackDependent => true,
+
+ EvaluatedToOkModuloOpaqueTypes
+ | EvaluatedToOk
+ | EvaluatedToOkModuloRegions
+ | EvaluatedToAmbig
+ | EvaluatedToErr => false,
+ }
+ }
+}
+
/// Indicates that trait evaluation caused overflow and in which pass.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum OverflowError {
diff --git a/crates/hir-ty/src/next_solver/infer/snapshot/mod.rs b/crates/hir-ty/src/next_solver/infer/snapshot/mod.rs
index 7b9ca96c51..705aa43fb1 100644
--- a/crates/hir-ty/src/next_solver/infer/snapshot/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/snapshot/mod.rs
@@ -109,4 +109,17 @@ impl<'db> InferCtxt<'db> {
self.rollback_to(snapshot);
r
}
+
+ /// Scan the constraints produced since `snapshot` and check whether
+ /// we added any region constraints.
+ pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot) -> bool {
+ self.inner
+ .borrow_mut()
+ .unwrap_region_constraints()
+ .region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
+ }
+
+ pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot) -> bool {
+ self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
+ }
}
diff --git a/crates/hir-ty/src/next_solver/infer/traits.rs b/crates/hir-ty/src/next_solver/infer/traits.rs
index 68aa12d7bb..9fa1fa7fb4 100644
--- a/crates/hir-ty/src/next_solver/infer/traits.rs
+++ b/crates/hir-ty/src/next_solver/infer/traits.rs
@@ -7,16 +7,18 @@ use std::{
hash::{Hash, Hasher},
};
+use hir_def::TraitId;
use rustc_type_ir::elaborate::Elaboratable;
use rustc_type_ir::{
PredicatePolarity, Upcast,
solve::{Certainty, NoSolution},
};
use rustc_type_ir::{TypeFoldable, TypeVisitable};
+use tracing::debug;
use crate::next_solver::{
Binder, Clause, DbInterner, Goal, ParamEnv, PolyTraitPredicate, Predicate, SolverDefId, Span,
- TraitPredicate, Ty,
+ TraitPredicate, TraitRef, Ty,
};
use super::InferCtxt;
@@ -237,3 +239,35 @@ impl<'db, O> Obligation<'db, O> {
Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
}
}
+
+/// Determines whether the type `ty` is known to meet `bound` and
+/// returns true if so. Returns false if `ty` either does not meet
+/// `bound` or is not known to meet bound (note that this is
+/// conservative towards *no impl*, which is the opposite of the
+/// `evaluate` methods).
+pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+ def_id: TraitId,
+) -> bool {
+ let trait_ref = TraitRef::new(infcx.interner, def_id.into(), [ty]);
+ pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref)
+}
+
+/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?
+///
+/// Ping me on zulip if you want to use this method and need help with finding
+/// an appropriate replacement.
+fn pred_known_to_hold_modulo_regions<'db>(
+ infcx: &InferCtxt<'db>,
+ param_env: ParamEnv<'db>,
+ pred: impl Upcast<DbInterner<'db>, Predicate<'db>>,
+) -> bool {
+ let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), param_env, pred);
+
+ let result = infcx.evaluate_obligation(&obligation);
+ debug!(?result);
+
+ result.must_apply_modulo_regions()
+}
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index b72504a19c..6b91ee35eb 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -1616,7 +1616,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
mut f: impl FnMut(Self::ImplId),
) {
let trait_ = trait_.0;
- let self_ty_fp = TyFingerprint::for_trait_impl_ns(&self_ty);
+ let self_ty_fp = TyFingerprint::for_trait_impl(self_ty);
let fps: &[TyFingerprint] = match self_ty.kind() {
TyKind::Infer(InferTy::IntVar(..)) => &ALL_INT_FPS,
TyKind::Infer(InferTy::FloatVar(..)) => &ALL_FLOAT_FPS,
@@ -1907,7 +1907,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
match impl_trait_id {
crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
let infer = self.db().infer(func.into());
- EarlyBinder::bind(infer.type_of_rpit[idx].to_nextsolver(self))
+ EarlyBinder::bind(infer.type_of_rpit[idx.to_nextsolver(self)])
}
crate::ImplTraitId::TypeAliasImplTrait(..)
| crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
diff --git a/crates/hir-ty/src/next_solver/mapping.rs b/crates/hir-ty/src/next_solver/mapping.rs
index f3f74f67c0..b32a5ec292 100644
--- a/crates/hir-ty/src/next_solver/mapping.rs
+++ b/crates/hir-ty/src/next_solver/mapping.rs
@@ -143,10 +143,29 @@ pub 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 {
@@ -633,6 +652,16 @@ impl<'db> ChalkToNextSolver<'db, GenericArg<'db>> for chalk_ir::GenericArg<Inter
}
}
+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(
@@ -642,6 +671,17 @@ impl<'db> ChalkToNextSolver<'db, GenericArgs<'db>> for chalk_ir::Substitution<In
}
}
+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())
diff --git a/crates/hir-ty/src/next_solver/region.rs b/crates/hir-ty/src/next_solver/region.rs
index 0bfd2b8003..32c30d19c7 100644
--- a/crates/hir-ty/src/next_solver/region.rs
+++ b/crates/hir-ty/src/next_solver/region.rs
@@ -17,12 +17,18 @@ use super::{
pub type RegionKind<'db> = rustc_type_ir::RegionKind<DbInterner<'db>>;
-#[salsa::interned(constructor = new_, debug)]
+#[salsa::interned(constructor = new_)]
pub struct Region<'db> {
#[returns(ref)]
kind_: RegionKind<'db>,
}
+impl std::fmt::Debug for Region<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.kind().fmt(f)
+ }
+}
+
impl<'db> Region<'db> {
pub fn new(interner: DbInterner<'db>, kind: RegionKind<'db>) -> Self {
Region::new_(interner.db(), kind)
@@ -69,6 +75,10 @@ impl<'db> Region<'db> {
matches!(self.inner(), RegionKind::ReVar(_))
}
+ pub fn is_error(&self) -> bool {
+ matches!(self.inner(), RegionKind::ReError(_))
+ }
+
pub fn error(interner: DbInterner<'db>) -> Self {
Region::new(interner, RegionKind::ReError(ErrorGuaranteed))
}
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index a25996ab48..5ccd84af8d 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -3,7 +3,8 @@
use std::iter;
use std::ops::ControlFlow;
-use hir_def::{GenericDefId, TypeOrConstParamId, TypeParamId};
+use hir_def::type_ref::Rawness;
+use hir_def::{AdtId, GenericDefId, TypeOrConstParamId, TypeParamId};
use intern::{Interned, Symbol, sym};
use rustc_abi::{Float, Integer, Size};
use rustc_ast_ir::{Mutability, try_visit, visit::VisitorResult};
@@ -13,7 +14,7 @@ use rustc_type_ir::{
IntTy, IntVid, Interner, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor, UintTy, WithCachedTypeInfo,
inherent::{
- Abi, AdtDef, BoundVarLike, Const as _, GenericArgs as _, IntoKind, ParamLike,
+ Abi, AdtDef as _, BoundVarLike, Const as _, GenericArgs as _, IntoKind, ParamLike,
PlaceholderLike, Safety as _, SliceLike, Ty as _,
},
relate::Relate,
@@ -23,6 +24,7 @@ use rustc_type_ir::{
use salsa::plumbing::{AsId, FromId};
use smallvec::SmallVec;
+use crate::next_solver::{AdtDef, Binder};
use crate::{
FnAbi,
db::HirDatabase,
@@ -75,6 +77,10 @@ impl<'db> Ty<'db> {
.unwrap()
}
+ pub fn new_adt(interner: DbInterner<'db>, adt_id: AdtId, args: GenericArgs<'db>) -> Self {
+ Ty::new(interner, TyKind::Adt(AdtDef::new(adt_id, interner), args))
+ }
+
pub fn new_param(interner: DbInterner<'db>, id: TypeParamId, index: u32, name: Symbol) -> Self {
Ty::new(interner, TyKind::Param(ParamTy { id, index }))
}
@@ -338,6 +344,23 @@ impl<'db> Ty<'db> {
}
#[inline]
+ pub fn is_raw_ptr(self) -> bool {
+ matches!(self.kind(), TyKind::RawPtr(..))
+ }
+
+ pub fn is_union(self) -> bool {
+ self.as_adt().is_some_and(|(adt, _)| matches!(adt, AdtId::UnionId(_)))
+ }
+
+ #[inline]
+ pub fn as_adt(self) -> Option<(AdtId, GenericArgs<'db>)> {
+ match self.kind() {
+ TyKind::Adt(adt_def, args) => Some((adt_def.def_id().0, args)),
+ _ => None,
+ }
+ }
+
+ #[inline]
pub fn ty_vid(self) -> Option<TyVid> {
match self.kind() {
TyKind::Infer(rustc_type_ir::TyVar(vid)) => Some(vid),
@@ -372,6 +395,38 @@ impl<'db> Ty<'db> {
pub fn references_non_lt_error(self) -> bool {
self.references_error() && self.visit_with(&mut ReferencesNonLifetimeError).is_break()
}
+
+ pub fn callable_sig(self, interner: DbInterner<'db>) -> Option<Binder<'db, FnSig<'db>>> {
+ match self.kind() {
+ TyKind::FnDef(callable, args) => {
+ Some(interner.fn_sig(callable).instantiate(interner, args))
+ }
+ TyKind::FnPtr(sig, hdr) => Some(sig.with(hdr)),
+ TyKind::Closure(closure_id, closure_args) => closure_args
+ .split_closure_args_untupled()
+ .closure_sig_as_fn_ptr_ty
+ .callable_sig(interner),
+ _ => None,
+ }
+ }
+
+ pub fn as_reference_or_ptr(self) -> Option<(Ty<'db>, Rawness, Mutability)> {
+ match self.kind() {
+ TyKind::Ref(_, ty, mutability) => Some((ty, Rawness::Ref, mutability)),
+ TyKind::RawPtr(ty, mutability) => Some((ty, Rawness::RawPtr, mutability)),
+ _ => None,
+ }
+ }
+
+ /// Replace infer vars with errors.
+ ///
+ /// This needs to be called for every type that may contain infer vars and is yielded to outside inference,
+ /// as things other than inference do not expect to see infer vars.
+ pub fn replace_infer_with_error(self, interner: DbInterner<'db>) -> Ty<'db> {
+ self.fold_with(&mut crate::next_solver::infer::resolve::ReplaceInferWithError::new(
+ interner,
+ ))
+ }
}
struct ReferencesNonLifetimeError;
@@ -928,11 +983,17 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
interned_vec_db!(Tys, Ty);
+impl<'db> Tys<'db> {
+ pub fn inputs(&self) -> &[Ty<'db>] {
+ self.as_slice().split_last().unwrap().1
+ }
+}
+
impl<'db> rustc_type_ir::inherent::Tys<DbInterner<'db>> for Tys<'db> {
fn inputs(self) -> <DbInterner<'db> as rustc_type_ir::Interner>::FnInputTys {
Tys::new_from_iter(
DbInterner::conjure(),
- self.as_slice().split_last().unwrap().1.iter().cloned(),
+ self.as_slice().split_last().unwrap().1.iter().copied(),
)
}
diff --git a/crates/hir-ty/src/next_solver/util.rs b/crates/hir-ty/src/next_solver/util.rs
index a7f9817f9c..750d09e1a7 100644
--- a/crates/hir-ty/src/next_solver/util.rs
+++ b/crates/hir-ty/src/next_solver/util.rs
@@ -413,7 +413,7 @@ pub(crate) fn for_trait_impls(
let trait_module = trait_id.module(db);
let type_module = match self_ty_fp {
Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(db)),
- Some(TyFingerprint::ForeignType(type_id)) => Some(from_foreign_def_id(type_id).module(db)),
+ Some(TyFingerprint::ForeignType(type_id)) => Some(type_id.module(db)),
Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(db)),
_ => None,
};
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 1c3da438cb..5dd9ab7532 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -36,10 +36,11 @@ use test_fixture::WithFixture;
use triomphe::Arc;
use crate::{
- InferenceResult, Ty,
+ InferenceResult,
db::HirDatabase,
display::{DisplayTarget, HirDisplay},
infer::{Adjustment, TypeMismatch},
+ next_solver::Ty,
setup_tracing,
test_db::TestDB,
};
@@ -78,172 +79,172 @@ fn check_impl(
let _tracing = setup_tracing();
let (db, files) = TestDB::with_many_files(ra_fixture);
- let mut had_annotations = false;
- let mut mismatches = FxHashMap::default();
- let mut types = FxHashMap::default();
- let mut adjustments = FxHashMap::default();
- for (file_id, annotations) in db.extract_annotations() {
- for (range, expected) in annotations {
- let file_range = FileRange { file_id, range };
- if only_types {
- types.insert(file_range, expected);
- } else if expected.starts_with("type: ") {
- types.insert(file_range, expected.trim_start_matches("type: ").to_owned());
- } else if expected.starts_with("expected") {
- mismatches.insert(file_range, expected);
- } else if expected.starts_with("adjustments:") {
- adjustments.insert(
- file_range,
- expected.trim_start_matches("adjustments:").trim().to_owned(),
- );
- } else {
- panic!("unexpected annotation: {expected} @ {range:?}");
+ salsa::attach(&db, || {
+ let mut had_annotations = false;
+ let mut mismatches = FxHashMap::default();
+ let mut types = FxHashMap::default();
+ let mut adjustments = FxHashMap::default();
+ for (file_id, annotations) in db.extract_annotations() {
+ for (range, expected) in annotations {
+ let file_range = FileRange { file_id, range };
+ if only_types {
+ types.insert(file_range, expected);
+ } else if expected.starts_with("type: ") {
+ types.insert(file_range, expected.trim_start_matches("type: ").to_owned());
+ } else if expected.starts_with("expected") {
+ mismatches.insert(file_range, expected);
+ } else if expected.starts_with("adjustments:") {
+ adjustments.insert(
+ file_range,
+ expected.trim_start_matches("adjustments:").trim().to_owned(),
+ );
+ } else {
+ panic!("unexpected annotation: {expected} @ {range:?}");
+ }
+ had_annotations = true;
}
- had_annotations = true;
}
- }
- assert!(had_annotations || allow_none, "no `//^` annotations found");
-
- let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
- for file_id in files {
- let module = db.module_for_file_opt(file_id.file_id(&db));
- let module = match module {
- Some(m) => m,
- None => continue,
- };
- let def_map = module.def_map(&db);
- visit_module(&db, def_map, module.local_id, &mut |it| {
- let def = match it {
- ModuleDefId::FunctionId(it) => it.into(),
- ModuleDefId::EnumVariantId(it) => it.into(),
- ModuleDefId::ConstId(it) => it.into(),
- ModuleDefId::StaticId(it) => it.into(),
- _ => return,
+ assert!(had_annotations || allow_none, "no `//^` annotations found");
+
+ let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
+ for file_id in files {
+ let module = db.module_for_file_opt(file_id.file_id(&db));
+ let module = match module {
+ Some(m) => m,
+ None => continue,
};
- defs.push((def, module.krate()))
- });
- }
- defs.sort_by_key(|(def, _)| match def {
- DefWithBodyId::FunctionId(it) => {
- let loc = it.lookup(&db);
- loc.source(&db).value.syntax().text_range().start()
- }
- DefWithBodyId::ConstId(it) => {
- let loc = it.lookup(&db);
- loc.source(&db).value.syntax().text_range().start()
- }
- DefWithBodyId::StaticId(it) => {
- let loc = it.lookup(&db);
- loc.source(&db).value.syntax().text_range().start()
- }
- DefWithBodyId::VariantId(it) => {
- let loc = it.lookup(&db);
- loc.source(&db).value.syntax().text_range().start()
+ let def_map = module.def_map(&db);
+ visit_module(&db, def_map, module.local_id, &mut |it| {
+ let def = match it {
+ ModuleDefId::FunctionId(it) => it.into(),
+ ModuleDefId::EnumVariantId(it) => it.into(),
+ ModuleDefId::ConstId(it) => it.into(),
+ ModuleDefId::StaticId(it) => it.into(),
+ _ => return,
+ };
+ defs.push((def, module.krate()))
+ });
}
- });
- let mut unexpected_type_mismatches = String::new();
- for (def, krate) in defs {
- let display_target = DisplayTarget::from_crate(&db, krate);
- let (body, body_source_map) = db.body_with_source_map(def);
- let inference_result = db.infer(def);
-
- for (pat, mut ty) in inference_result.type_of_pat.iter() {
- if let Pat::Bind { id, .. } = body[pat] {
- ty = &inference_result.type_of_binding[id];
+ defs.sort_by_key(|(def, _)| match def {
+ DefWithBodyId::FunctionId(it) => {
+ let loc = it.lookup(&db);
+ loc.source(&db).value.syntax().text_range().start()
}
- let node = match pat_node(&body_source_map, pat, &db) {
- Some(value) => value,
- None => continue,
- };
- let range = node.as_ref().original_file_range_rooted(&db);
- if let Some(expected) = types.remove(&range) {
- let actual = salsa::attach(&db, || {
- if display_source {
+ DefWithBodyId::ConstId(it) => {
+ let loc = it.lookup(&db);
+ loc.source(&db).value.syntax().text_range().start()
+ }
+ DefWithBodyId::StaticId(it) => {
+ let loc = it.lookup(&db);
+ loc.source(&db).value.syntax().text_range().start()
+ }
+ DefWithBodyId::VariantId(it) => {
+ let loc = it.lookup(&db);
+ loc.source(&db).value.syntax().text_range().start()
+ }
+ });
+ let mut unexpected_type_mismatches = String::new();
+ for (def, krate) in defs {
+ let display_target = DisplayTarget::from_crate(&db, krate);
+ let (body, body_source_map) = db.body_with_source_map(def);
+ let inference_result = db.infer(def);
+
+ for (pat, mut ty) in inference_result.type_of_pat.iter() {
+ if let Pat::Bind { id, .. } = body[pat] {
+ ty = &inference_result.type_of_binding[id];
+ }
+ let node = match pat_node(&body_source_map, pat, &db) {
+ Some(value) => value,
+ None => continue,
+ };
+ let range = node.as_ref().original_file_range_rooted(&db);
+ if let Some(expected) = types.remove(&range) {
+ let actual = if display_source {
ty.display_source_code(&db, def.module(&db), true).unwrap()
} else {
ty.display_test(&db, display_target).to_string()
- }
- });
- assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range);
+ };
+ assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range);
+ }
}
- }
- for (expr, ty) in inference_result.type_of_expr.iter() {
- let node = match expr_node(&body_source_map, expr, &db) {
- Some(value) => value,
- None => continue,
- };
- let range = node.as_ref().original_file_range_rooted(&db);
- if let Some(expected) = types.remove(&range) {
- let actual = salsa::attach(&db, || {
- if display_source {
+ for (expr, ty) in inference_result.type_of_expr.iter() {
+ let node = match expr_node(&body_source_map, expr, &db) {
+ Some(value) => value,
+ None => continue,
+ };
+ let range = node.as_ref().original_file_range_rooted(&db);
+ if let Some(expected) = types.remove(&range) {
+ let actual = if display_source {
ty.display_source_code(&db, def.module(&db), true).unwrap()
} else {
ty.display_test(&db, display_target).to_string()
- }
- });
- assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range);
- }
- if let Some(expected) = adjustments.remove(&range) {
- let adjustments = inference_result
- .expr_adjustments
- .get(&expr)
- .map_or_else(Default::default, |it| &**it);
- assert_eq!(
- expected,
- adjustments
- .iter()
- .map(|Adjustment { kind, .. }| format!("{kind:?}"))
- .join(", ")
- );
+ };
+ assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range);
+ }
+ if let Some(expected) = adjustments.remove(&range) {
+ let adjustments = inference_result
+ .expr_adjustments
+ .get(&expr)
+ .map_or_else(Default::default, |it| &**it);
+ assert_eq!(
+ expected,
+ adjustments
+ .iter()
+ .map(|Adjustment { kind, .. }| format!("{kind:?}"))
+ .join(", ")
+ );
+ }
}
- }
- for (expr_or_pat, mismatch) in inference_result.type_mismatches() {
- let Some(node) = (match expr_or_pat {
- hir_def::hir::ExprOrPatId::ExprId(expr) => expr_node(&body_source_map, expr, &db),
- hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(&body_source_map, pat, &db),
- }) else {
- continue;
- };
- let range = node.as_ref().original_file_range_rooted(&db);
- let actual = salsa::attach(&db, || {
- format!(
+ for (expr_or_pat, mismatch) in inference_result.type_mismatches() {
+ let Some(node) = (match expr_or_pat {
+ hir_def::hir::ExprOrPatId::ExprId(expr) => {
+ expr_node(&body_source_map, expr, &db)
+ }
+ hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(&body_source_map, pat, &db),
+ }) else {
+ continue;
+ };
+ let range = node.as_ref().original_file_range_rooted(&db);
+ let actual = format!(
"expected {}, got {}",
mismatch.expected.display_test(&db, display_target),
mismatch.actual.display_test(&db, display_target)
- )
- });
- match mismatches.remove(&range) {
- Some(annotation) => assert_eq!(actual, annotation),
- None => format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual),
+ );
+ match mismatches.remove(&range) {
+ Some(annotation) => assert_eq!(actual, annotation),
+ None => {
+ format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual)
+ }
+ }
}
}
- }
- let mut buf = String::new();
- if !unexpected_type_mismatches.is_empty() {
- format_to!(buf, "Unexpected type mismatches:\n{}", unexpected_type_mismatches);
- }
- if !mismatches.is_empty() {
- format_to!(buf, "Unchecked mismatch annotations:\n");
- for m in mismatches {
- format_to!(buf, "{:?}: {}\n", m.0.range, m.1);
+ let mut buf = String::new();
+ if !unexpected_type_mismatches.is_empty() {
+ format_to!(buf, "Unexpected type mismatches:\n{}", unexpected_type_mismatches);
}
- }
- if !types.is_empty() {
- format_to!(buf, "Unchecked type annotations:\n");
- for t in types {
- format_to!(buf, "{:?}: type {}\n", t.0.range, t.1);
+ if !mismatches.is_empty() {
+ format_to!(buf, "Unchecked mismatch annotations:\n");
+ for m in mismatches {
+ format_to!(buf, "{:?}: {}\n", m.0.range, m.1);
+ }
}
- }
- if !adjustments.is_empty() {
- format_to!(buf, "Unchecked adjustments annotations:\n");
- for t in adjustments {
- format_to!(buf, "{:?}: type {:?}\n", t.0.range, t.1);
+ if !types.is_empty() {
+ format_to!(buf, "Unchecked type annotations:\n");
+ for t in types {
+ format_to!(buf, "{:?}: type {}\n", t.0.range, t.1);
+ }
}
- }
- assert!(buf.is_empty(), "{}", buf);
+ if !adjustments.is_empty() {
+ format_to!(buf, "Unchecked adjustments annotations:\n");
+ for t in adjustments {
+ format_to!(buf, "{:?}: type {:?}\n", t.0.range, t.1);
+ }
+ }
+ assert!(buf.is_empty(), "{}", buf);
+ });
}
fn expr_node(
@@ -282,139 +283,140 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let _tracing = setup_tracing();
let (db, file_id) = TestDB::with_single_file(content);
- let mut buf = String::new();
-
- let mut infer_def = |inference_result: Arc<InferenceResult>,
- body: Arc<Body>,
- body_source_map: Arc<BodySourceMap>,
- krate: Crate| {
- let display_target = DisplayTarget::from_crate(&db, krate);
- let mut types: Vec<(InFile<SyntaxNode>, &Ty)> = Vec::new();
- let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch)> = Vec::new();
-
- if let Some(self_param) = body.self_param {
- let ty = &inference_result.type_of_binding[self_param];
- if let Some(syntax_ptr) = body_source_map.self_param_syntax() {
- let root = db.parse_or_expand(syntax_ptr.file_id);
- let node = syntax_ptr.map(|ptr| ptr.to_node(&root).syntax().clone());
- types.push((node, ty));
+ salsa::attach(&db, || {
+ let mut buf = String::new();
+
+ let mut infer_def = |inference_result: Arc<InferenceResult<'_>>,
+ body: Arc<Body>,
+ body_source_map: Arc<BodySourceMap>,
+ krate: Crate| {
+ let display_target = DisplayTarget::from_crate(&db, krate);
+ let mut types: Vec<(InFile<SyntaxNode>, &Ty<'_>)> = Vec::new();
+ let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch<'_>)> = Vec::new();
+
+ if let Some(self_param) = body.self_param {
+ let ty = &inference_result.type_of_binding[self_param];
+ if let Some(syntax_ptr) = body_source_map.self_param_syntax() {
+ let root = db.parse_or_expand(syntax_ptr.file_id);
+ let node = syntax_ptr.map(|ptr| ptr.to_node(&root).syntax().clone());
+ types.push((node, ty));
+ }
}
- }
- for (pat, mut ty) in inference_result.type_of_pat.iter() {
- if let Pat::Bind { id, .. } = body[pat] {
- ty = &inference_result.type_of_binding[id];
- }
- let node = match body_source_map.pat_syntax(pat) {
- Ok(sp) => {
- let root = db.parse_or_expand(sp.file_id);
- sp.map(|ptr| ptr.to_node(&root).syntax().clone())
+ for (pat, mut ty) in inference_result.type_of_pat.iter() {
+ if let Pat::Bind { id, .. } = body[pat] {
+ ty = &inference_result.type_of_binding[id];
+ }
+ let node = match body_source_map.pat_syntax(pat) {
+ Ok(sp) => {
+ let root = db.parse_or_expand(sp.file_id);
+ sp.map(|ptr| ptr.to_node(&root).syntax().clone())
+ }
+ Err(SyntheticSyntax) => continue,
+ };
+ types.push((node.clone(), ty));
+ if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat) {
+ mismatches.push((node, mismatch));
}
- Err(SyntheticSyntax) => continue,
- };
- types.push((node.clone(), ty));
- if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat) {
- mismatches.push((node, mismatch));
}
- }
- for (expr, ty) in inference_result.type_of_expr.iter() {
- let node = match body_source_map.expr_syntax(expr) {
- Ok(sp) => {
- let root = db.parse_or_expand(sp.file_id);
- sp.map(|ptr| ptr.to_node(&root).syntax().clone())
+ for (expr, ty) in inference_result.type_of_expr.iter() {
+ let node = match body_source_map.expr_syntax(expr) {
+ Ok(sp) => {
+ let root = db.parse_or_expand(sp.file_id);
+ sp.map(|ptr| ptr.to_node(&root).syntax().clone())
+ }
+ Err(SyntheticSyntax) => continue,
+ };
+ types.push((node.clone(), ty));
+ if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) {
+ mismatches.push((node, mismatch));
}
- Err(SyntheticSyntax) => continue,
- };
- types.push((node.clone(), ty));
- if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) {
- mismatches.push((node, mismatch));
}
- }
- // sort ranges for consistency
- types.sort_by_key(|(node, _)| {
- let range = node.value.text_range();
- (range.start(), range.end())
- });
- for (node, ty) in &types {
- let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.value.clone()) {
- (self_param.name().unwrap().syntax().text_range(), "self".to_owned())
- } else {
- (node.value.text_range(), node.value.text().to_string().replace('\n', " "))
- };
- let macro_prefix = if node.file_id != file_id { "!" } else { "" };
- format_to!(
- buf,
- "{}{:?} '{}': {}\n",
- macro_prefix,
- range,
- ellipsize(text, 15),
- ty.display_test(&db, display_target)
- );
- }
- if include_mismatches {
- mismatches.sort_by_key(|(node, _)| {
+ // sort ranges for consistency
+ types.sort_by_key(|(node, _)| {
let range = node.value.text_range();
(range.start(), range.end())
});
- for (src_ptr, mismatch) in &mismatches {
- let range = src_ptr.value.text_range();
- let macro_prefix = if src_ptr.file_id != file_id { "!" } else { "" };
+ for (node, ty) in &types {
+ let (range, text) =
+ if let Some(self_param) = ast::SelfParam::cast(node.value.clone()) {
+ (self_param.name().unwrap().syntax().text_range(), "self".to_owned())
+ } else {
+ (node.value.text_range(), node.value.text().to_string().replace('\n', " "))
+ };
+ let macro_prefix = if node.file_id != file_id { "!" } else { "" };
format_to!(
buf,
- "{}{:?}: expected {}, got {}\n",
+ "{}{:?} '{}': {}\n",
macro_prefix,
range,
- mismatch.expected.display_test(&db, display_target),
- mismatch.actual.display_test(&db, display_target),
+ ellipsize(text, 15),
+ ty.display_test(&db, display_target)
);
}
- }
- };
+ if include_mismatches {
+ mismatches.sort_by_key(|(node, _)| {
+ let range = node.value.text_range();
+ (range.start(), range.end())
+ });
+ for (src_ptr, mismatch) in &mismatches {
+ let range = src_ptr.value.text_range();
+ let macro_prefix = if src_ptr.file_id != file_id { "!" } else { "" };
+ format_to!(
+ buf,
+ "{}{:?}: expected {}, got {}\n",
+ macro_prefix,
+ range,
+ mismatch.expected.display_test(&db, display_target),
+ mismatch.actual.display_test(&db, display_target),
+ );
+ }
+ }
+ };
- let module = db.module_for_file(file_id.file_id(&db));
- let def_map = module.def_map(&db);
+ let module = db.module_for_file(file_id.file_id(&db));
+ let def_map = module.def_map(&db);
- let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
- visit_module(&db, def_map, module.local_id, &mut |it| {
- let def = match it {
- ModuleDefId::FunctionId(it) => it.into(),
- ModuleDefId::EnumVariantId(it) => it.into(),
- ModuleDefId::ConstId(it) => it.into(),
- ModuleDefId::StaticId(it) => it.into(),
- _ => return,
- };
- defs.push((def, module.krate()))
- });
- defs.sort_by_key(|(def, _)| match def {
- DefWithBodyId::FunctionId(it) => {
- let loc = it.lookup(&db);
- loc.source(&db).value.syntax().text_range().start()
- }
- DefWithBodyId::ConstId(it) => {
- let loc = it.lookup(&db);
- loc.source(&db).value.syntax().text_range().start()
- }
- DefWithBodyId::StaticId(it) => {
- let loc = it.lookup(&db);
- loc.source(&db).value.syntax().text_range().start()
- }
- DefWithBodyId::VariantId(it) => {
- let loc = it.lookup(&db);
- loc.source(&db).value.syntax().text_range().start()
- }
- });
- for (def, krate) in defs {
- let (body, source_map) = db.body_with_source_map(def);
- let infer = db.infer(def);
- salsa::attach(&db, || {
+ let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
+ visit_module(&db, def_map, module.local_id, &mut |it| {
+ let def = match it {
+ ModuleDefId::FunctionId(it) => it.into(),
+ ModuleDefId::EnumVariantId(it) => it.into(),
+ ModuleDefId::ConstId(it) => it.into(),
+ ModuleDefId::StaticId(it) => it.into(),
+ _ => return,
+ };
+ defs.push((def, module.krate()))
+ });
+ defs.sort_by_key(|(def, _)| match def {
+ DefWithBodyId::FunctionId(it) => {
+ let loc = it.lookup(&db);
+ loc.source(&db).value.syntax().text_range().start()
+ }
+ DefWithBodyId::ConstId(it) => {
+ let loc = it.lookup(&db);
+ loc.source(&db).value.syntax().text_range().start()
+ }
+ DefWithBodyId::StaticId(it) => {
+ let loc = it.lookup(&db);
+ loc.source(&db).value.syntax().text_range().start()
+ }
+ DefWithBodyId::VariantId(it) => {
+ let loc = it.lookup(&db);
+ loc.source(&db).value.syntax().text_range().start()
+ }
+ });
+ for (def, krate) in defs {
+ let (body, source_map) = db.body_with_source_map(def);
+ let infer = db.infer(def);
infer_def(infer, body, source_map, krate);
- })
- }
+ }
- buf.truncate(buf.trim_end().len());
- buf
+ buf.truncate(buf.trim_end().len());
+ buf
+ })
}
pub(crate) fn visit_module(
diff --git a/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs
index b001ac1e82..d3bc26abd7 100644
--- a/crates/hir-ty/src/tests/closure_captures.rs
+++ b/crates/hir-ty/src/tests/closure_captures.rs
@@ -2,15 +2,16 @@ use expect_test::{Expect, expect};
use hir_def::db::DefDatabase;
use hir_expand::{HirFileId, files::InFileWrapper};
use itertools::Itertools;
-use salsa::plumbing::FromId;
use span::TextRange;
use syntax::{AstNode, AstPtr};
use test_fixture::WithFixture;
-use crate::db::{HirDatabase, InternedClosureId};
-use crate::display::{DisplayTarget, HirDisplay};
-use crate::mir::MirSpan;
-use crate::test_db::TestDB;
+use crate::{
+ db::HirDatabase,
+ display::{DisplayTarget, HirDisplay},
+ mir::MirSpan,
+ test_db::TestDB,
+};
use super::{setup_tracing, visit_module};
@@ -35,7 +36,7 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
let infer = db.infer(def);
let db = &db;
captures_info.extend(infer.closure_info.iter().flat_map(|(closure_id, (captures, _))| {
- let closure = db.lookup_intern_closure(InternedClosureId::from_id(closure_id.0));
+ let closure = db.lookup_intern_closure(*closure_id);
let source_map = db.body_with_source_map(closure.0).1;
let closure_text_range = source_map
.expr_syntax(closure.1)
@@ -70,7 +71,7 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
let capture_ty = salsa::attach(db, || {
capture
.ty
- .skip_binders()
+ .skip_binder()
.display_test(db, DisplayTarget::from_crate(db, module.krate()))
.to_string()
});
diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs
index 1735f550b8..5a53db4b7a 100644
--- a/crates/hir-ty/src/tests/coercion.rs
+++ b/crates/hir-ty/src/tests/coercion.rs
@@ -49,7 +49,7 @@ fn let_stmt_coerce() {
//- minicore: coerce_unsized
fn test() {
let x: &[isize] = &[1];
- // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
+ // ^^^^ adjustments: Deref(None), Borrow(Ref('?2, Not)), Pointer(Unsize)
let x: *const [isize] = &[1];
// ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
}
@@ -268,7 +268,7 @@ fn takes_ref_str(x: &str) {}
fn returns_string() -> String { loop {} }
fn test() {
takes_ref_str(&{ returns_string() });
- // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('{error}, Not))
+ // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('{region error}, Not))
}
"#,
);
@@ -567,7 +567,7 @@ trait Foo {}
fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
let _: &dyn Foo = &f;
let _: &dyn Foo = g;
- //^ expected &'? (dyn Foo + '?), got &'? impl Foo + ?Sized
+ //^ expected &'? (dyn Foo + 'static), got &'? impl Foo + ?Sized
}
"#,
);
@@ -833,11 +833,11 @@ struct V<T> { t: T }
fn main() {
let a: V<&dyn Tr>;
(a,) = V { t: &S };
- //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,)
+ //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + 'static)>,)
let mut a: V<&dyn Tr> = V { t: &S };
(a,) = V { t: &S };
- //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,)
+ //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + 'static)>,)
}
"#,
);
@@ -854,8 +854,8 @@ impl core::cmp::PartialEq for Struct {
}
fn test() {
Struct == Struct;
- // ^^^^^^ adjustments: Borrow(Ref('{error}, Not))
- // ^^^^^^ adjustments: Borrow(Ref('{error}, Not))
+ // ^^^^^^ adjustments: Borrow(Ref('{region error}, Not))
+ // ^^^^^^ adjustments: Borrow(Ref('{region error}, Not))
}",
);
}
@@ -871,7 +871,7 @@ impl core::ops::AddAssign for Struct {
}
fn test() {
Struct += Struct;
- // ^^^^^^ adjustments: Borrow(Ref('{error}, Mut))
+ // ^^^^^^ adjustments: Borrow(Ref('{region error}, Mut))
// ^^^^^^ adjustments:
}",
);
diff --git a/crates/hir-ty/src/tests/display_source_code.rs b/crates/hir-ty/src/tests/display_source_code.rs
index 6e3faa05a6..a986b54a7b 100644
--- a/crates/hir-ty/src/tests/display_source_code.rs
+++ b/crates/hir-ty/src/tests/display_source_code.rs
@@ -67,11 +67,11 @@ trait B: A {}
fn test<'a>(
_: &(dyn A<Assoc = ()> + Send),
- //^ &(dyn A<Assoc = ()> + Send)
+ //^ &(dyn A<Assoc = ()> + Send + 'static)
_: &'a (dyn Send + A<Assoc = ()>),
- //^ &'a (dyn A<Assoc = ()> + Send)
+ //^ &'a (dyn A<Assoc = ()> + Send + 'static)
_: &dyn B<Assoc = ()>,
- //^ &(dyn B<Assoc = ()>)
+ //^ &(dyn B<Assoc = ()> + 'static)
) {}
"#,
);
@@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
trait Foo<'a> {}
fn foo(foo: &dyn for<'a> Foo<'a>) {}
- // ^^^ &dyn Foo<'?>
+ // ^^^ &(dyn Foo<'?> + 'static)
"#,
);
}
diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs
index 8587c13e87..ce3de06127 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_shim",
+ "return_type_impl_traits_ns_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_shim",
+ "return_type_impl_traits_ns_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_shim",
+ "return_type_impl_traits_ns_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_shim",
+ "return_type_impl_traits_ns_shim",
"expr_scopes_shim",
]
"#]],
@@ -586,7 +586,7 @@ fn main() {
"attrs_shim",
"attrs_shim",
"generic_predicates_ns_shim",
- "return_type_impl_traits_shim",
+ "return_type_impl_traits_ns_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_shim",
+ "generic_predicates_ns_shim",
"value_ty_shim",
"VariantFields::firewall_",
"VariantFields::query_",
@@ -610,7 +610,7 @@ fn main() {
"impl_self_ty_with_diagnostics_shim",
"generic_predicates_ns_shim",
"value_ty_shim",
- "generic_predicates_shim",
+ "generic_predicates_ns_shim",
]
"#]],
);
@@ -683,11 +683,12 @@ fn main() {
"attrs_shim",
"attrs_shim",
"generic_predicates_ns_shim",
- "return_type_impl_traits_shim",
+ "return_type_impl_traits_ns_shim",
"infer_shim",
"function_signature_with_source_map_shim",
"expr_scopes_shim",
"struct_signature_with_source_map_shim",
+ "generic_predicates_ns_shim",
"VariantFields::query_",
"inherent_impls_in_crate_shim",
"impl_signature_with_source_map_shim",
@@ -697,7 +698,7 @@ fn main() {
"impl_trait_with_diagnostics_shim",
"impl_self_ty_with_diagnostics_shim",
"generic_predicates_ns_shim",
- "generic_predicates_shim",
+ "generic_predicates_ns_shim",
]
"#]],
);
diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs
index 25b938c707..2f41de64cb 100644
--- a/crates/hir-ty/src/tests/macros.rs
+++ b/crates/hir-ty/src/tests/macros.rs
@@ -199,8 +199,8 @@ fn expr_macro_def_expanded_in_various_places() {
100..119 'for _ ...!() {}': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter
100..119 'for _ ...!() {}': <isize as IntoIterator>::IntoIter
100..119 'for _ ...!() {}': !
- 100..119 'for _ ...!() {}': <isize as IntoIterator>::IntoIter
- 100..119 'for _ ...!() {}': &'? mut <isize as IntoIterator>::IntoIter
+ 100..119 'for _ ...!() {}': {unknown}
+ 100..119 'for _ ...!() {}': &'? mut {unknown}
100..119 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
100..119 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item>
100..119 'for _ ...!() {}': ()
@@ -293,8 +293,8 @@ fn expr_macro_rules_expanded_in_various_places() {
114..133 'for _ ...!() {}': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter
114..133 'for _ ...!() {}': <isize as IntoIterator>::IntoIter
114..133 'for _ ...!() {}': !
- 114..133 'for _ ...!() {}': <isize as IntoIterator>::IntoIter
- 114..133 'for _ ...!() {}': &'? mut <isize as IntoIterator>::IntoIter
+ 114..133 'for _ ...!() {}': {unknown}
+ 114..133 'for _ ...!() {}': &'? mut {unknown}
114..133 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
114..133 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item>
114..133 'for _ ...!() {}': ()
diff --git a/crates/hir-ty/src/tests/method_resolution.rs b/crates/hir-ty/src/tests/method_resolution.rs
index 2f8f666475..b0afd60406 100644
--- a/crates/hir-ty/src/tests/method_resolution.rs
+++ b/crates/hir-ty/src/tests/method_resolution.rs
@@ -1157,9 +1157,9 @@ fn dyn_trait_super_trait_not_in_scope() {
51..55 'self': &'? Self
64..69 '{ 0 }': u32
66..67 '0': u32
- 176..177 'd': &'? (dyn Trait + '?)
+ 176..177 'd': &'? (dyn Trait + 'static)
191..207 '{ ...o(); }': ()
- 197..198 'd': &'? (dyn Trait + '?)
+ 197..198 'd': &'? (dyn Trait + 'static)
197..204 'd.foo()': u32
"#]],
);
@@ -2050,7 +2050,7 @@ impl dyn Error + Send {
/// Attempts to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
let err: Box<dyn Error> = self;
- // ^^^^ expected Box<dyn Error + '?>, got Box<dyn Error + Send + 'static>
+ // ^^^^ expected Box<dyn Error + 'static>, got Box<dyn Error + Send + 'static>
// FIXME, type mismatch should not occur
<dyn Error>::downcast(err).map_err(|_| loop {})
//^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + 'static>) -> Result<Box<{unknown}>, Box<dyn Error + 'static>>
diff --git a/crates/hir-ty/src/tests/opaque_types.rs b/crates/hir-ty/src/tests/opaque_types.rs
index 40e4c28fcc..5cdd170198 100644
--- a/crates/hir-ty/src/tests/opaque_types.rs
+++ b/crates/hir-ty/src/tests/opaque_types.rs
@@ -31,6 +31,7 @@ fn test() {
}
#[test]
+#[ignore = "FIXME(next-solver): This currently generates a type mismatch, need to switch opaque type handling to the solver"]
fn associated_type_impl_traits_complex() {
check_types(
r#"
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 00835aa031..7c79393e65 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1257,8 +1257,8 @@ fn test() {
16..66 'for _ ... }': fn into_iter<()>(()) -> <() as IntoIterator>::IntoIter
16..66 'for _ ... }': <() as IntoIterator>::IntoIter
16..66 'for _ ... }': !
- 16..66 'for _ ... }': <() as IntoIterator>::IntoIter
- 16..66 'for _ ... }': &'? mut <() as IntoIterator>::IntoIter
+ 16..66 'for _ ... }': {unknown}
+ 16..66 'for _ ... }': &'? mut {unknown}
16..66 'for _ ... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
16..66 'for _ ... }': Option<<{unknown} as Iterator>::Item>
16..66 'for _ ... }': ()
@@ -2363,8 +2363,8 @@ fn test() {
108..125 '{ ... }': usize
118..119 'N': usize
139..157 '{ ...= N; }': ()
- 149..150 '_': Foo<_>
- 153..154 'N': Foo<_>
+ 149..150 '_': Foo<N>
+ 153..154 'N': Foo<N>
"#]],
);
}
diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs
index c7711f31bf..e7fadd0363 100644
--- a/crates/hir-ty/src/tests/regression/new_solver.rs
+++ b/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -84,7 +84,7 @@ fn test() -> i32 {
307..359 'core::...n Foo)': DynMetadata<dyn Foo + '?>
327..328 '0': usize
327..340 '0 as *const F': *const F
- 327..358 '0 as *...yn Foo': *const (dyn Foo + '?)
+ 327..358 '0 as *...yn Foo': *const (dyn Foo + 'static)
370..371 'f': F
374..378 'F {}': F
388..395 'fat_ptr': *const (dyn Foo + '?)
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index 9d02a44c37..38af7cb724 100644
--- a/crates/hir-ty/src/tests/simple.rs
+++ b/crates/hir-ty/src/tests/simple.rs
@@ -2743,7 +2743,7 @@ impl B for Astruct {}
725..754 '#[rust...1i32])': Box<[i32; 1], Global>
747..753 '[1i32]': [i32; 1]
748..752 '1i32': i32
- 765..766 'v': Vec<Box<dyn B + '?, Global>, Global>
+ 765..766 'v': Vec<Box<dyn B + 'static, Global>, Global>
786..803 '<[_]> ...to_vec': fn into_vec<Box<dyn B + '?, Global>, Global>(Box<[Box<dyn B + '?, Global>], Global>) -> Vec<Box<dyn B + '?, Global>, Global>
786..860 '<[_]> ...ct)]))': Vec<Box<dyn B + '?, Global>, Global>
804..859 '#[rust...uct)])': Box<[Box<dyn B + '?, Global>; 1], Global>
@@ -3693,39 +3693,6 @@ fn main() {
}
#[test]
-fn infer_bad_lang_item() {
- check_infer(
- r#"
-#[lang="eq"]
-pub trait Eq {
- fn eq(&self, ) -> bool;
-
-}
-
-#[lang="shr"]
-pub trait Shr<RHS,Result> {
- fn shr(&self, rhs: &RHS) -> Result;
-}
-
-fn test() -> bool {
- 1 >> 1;
- 1 == 1;
-}
-"#,
- expect![[r#"
- 39..43 'self': &'? Self
- 114..118 'self': &'? Self
- 120..123 'rhs': &'? RHS
- 163..190 '{ ...= 1; }': bool
- 169..170 '1': i32
- 169..175 '1 >> 1': {unknown}
- 181..182 '1': i32
- 181..187 '1 == 1': {unknown}
- "#]],
- );
-}
-
-#[test]
fn macro_semitransparent_hygiene() {
check_types(
r#"
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 66faac09cc..0cf723e851 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -1480,24 +1480,24 @@ fn test(x: Box<dyn Trait<u64>>, y: &dyn Trait<u64>) {
expect![[r#"
29..33 'self': &'? Self
54..58 'self': &'? Self
- 206..208 '{}': Box<dyn Trait<u64> + '?>
- 218..219 'x': Box<dyn Trait<u64> + '?>
- 242..243 'y': &'? (dyn Trait<u64> + '?)
+ 206..208 '{}': Box<dyn Trait<u64> + 'static>
+ 218..219 'x': Box<dyn Trait<u64> + 'static>
+ 242..243 'y': &'? (dyn Trait<u64> + 'static)
262..379 '{ ...2(); }': ()
- 268..269 'x': Box<dyn Trait<u64> + '?>
- 275..276 'y': &'? (dyn Trait<u64> + '?)
+ 268..269 'x': Box<dyn Trait<u64> + 'static>
+ 275..276 'y': &'? (dyn Trait<u64> + 'static)
286..287 'z': Box<dyn Trait<u64> + '?>
290..293 'bar': fn bar() -> Box<dyn Trait<u64> + 'static>
290..295 'bar()': Box<dyn Trait<u64> + 'static>
- 301..302 'x': Box<dyn Trait<u64> + '?>
+ 301..302 'x': Box<dyn Trait<u64> + 'static>
301..308 'x.foo()': u64
- 314..315 'y': &'? (dyn Trait<u64> + '?)
+ 314..315 'y': &'? (dyn Trait<u64> + 'static)
314..321 'y.foo()': u64
327..328 'z': Box<dyn Trait<u64> + '?>
327..334 'z.foo()': u64
- 340..341 'x': Box<dyn Trait<u64> + '?>
+ 340..341 'x': Box<dyn Trait<u64> + 'static>
340..348 'x.foo2()': i64
- 354..355 'y': &'? (dyn Trait<u64> + '?)
+ 354..355 'y': &'? (dyn Trait<u64> + 'static)
354..362 'y.foo2()': i64
368..369 'z': Box<dyn Trait<u64> + '?>
368..376 'z.foo2()': i64
@@ -1528,7 +1528,7 @@ fn test(s: S<u32, i32>) {
expect![[r#"
32..36 'self': &'? Self
102..106 'self': &'? S<T, U>
- 128..139 '{ loop {} }': &'? (dyn Trait<T, U> + '?)
+ 128..139 '{ loop {} }': &'? (dyn Trait<T, U> + 'static)
130..137 'loop {}': !
135..137 '{}': ()
175..179 'self': &'? Self
@@ -1561,18 +1561,18 @@ fn test(x: Trait, y: &Trait) -> u64 {
}"#,
expect![[r#"
26..30 'self': &'? Self
- 60..62 '{}': dyn Trait + '?
- 72..73 'x': dyn Trait + '?
- 82..83 'y': &'? (dyn Trait + '?)
+ 60..62 '{}': dyn Trait + 'static
+ 72..73 'x': dyn Trait + 'static
+ 82..83 'y': &'? (dyn Trait + 'static)
100..175 '{ ...o(); }': u64
- 106..107 'x': dyn Trait + '?
- 113..114 'y': &'? (dyn Trait + '?)
+ 106..107 'x': dyn Trait + 'static
+ 113..114 'y': &'? (dyn Trait + 'static)
124..125 'z': dyn Trait + '?
128..131 'bar': fn bar() -> dyn Trait + 'static
128..133 'bar()': dyn Trait + 'static
- 139..140 'x': dyn Trait + '?
+ 139..140 'x': dyn Trait + 'static
139..146 'x.foo()': u64
- 152..153 'y': &'? (dyn Trait + '?)
+ 152..153 'y': &'? (dyn Trait + 'static)
152..159 'y.foo()': u64
165..166 'z': dyn Trait + '?
165..172 'z.foo()': u64
@@ -1594,7 +1594,7 @@ fn main() {
expect![[r#"
31..35 'self': &'? S
37..39 '{}': ()
- 47..48 '_': &'? (dyn Fn(S) + '?)
+ 47..48 '_': &'? (dyn Fn(S) + 'static)
58..60 '{}': ()
71..105 '{ ...()); }': ()
77..78 'f': fn f(&'? (dyn Fn(S) + 'static))
@@ -2948,13 +2948,13 @@ fn test(x: &dyn Foo) {
foo(x);
}"#,
expect![[r#"
- 21..22 'x': &'? (dyn Foo + '?)
+ 21..22 'x': &'? (dyn Foo + 'static)
34..36 '{}': ()
- 46..47 'x': &'? (dyn Foo + '?)
+ 46..47 'x': &'? (dyn Foo + 'static)
59..74 '{ foo(x); }': ()
65..68 'foo': fn foo(&'? (dyn Foo + 'static))
65..71 'foo(x)': ()
- 69..70 'x': &'? (dyn Foo + '?)
+ 69..70 'x': &'? (dyn Foo + 'static)
"#]],
);
}
@@ -3230,13 +3230,13 @@ fn foo() {
218..324 '{ ...&s); }': ()
228..229 's': Option<i32>
232..236 'None': Option<i32>
- 246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + '?>
- 281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + '?>
+ 246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static>
+ 281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + 'static>
294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option<i32>)
300..307 '|ps| {}': impl FnOnce(&'? Option<i32>)
301..303 'ps': &'? Option<i32>
305..307 '{}': ()
- 316..317 'f': Box<dyn FnOnce(&'? Option<i32>) + '?>
+ 316..317 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static>
316..321 'f(&s)': ()
318..320 '&s': &'? Option<i32>
319..320 's': Option<i32>
@@ -4272,10 +4272,10 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
"#,
expect![[r#"
90..94 'self': &'? Self
- 127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
+ 127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
164..195 '{ ...f(); }': ()
- 170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
- 170..184 'v.get::<i32>()': <dyn Trait<Assoc<i32> = &'a i32> + '? as Trait>::Assoc<i32>
+ 170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
+ 170..184 'v.get::<i32>()': <dyn Trait<Assoc<i32> = &'a i32> + 'static as Trait>::Assoc<i32>
170..192 'v.get:...eref()': {unknown}
"#]],
);
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 8ac152341e..16ad54a2f2 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -12,7 +12,7 @@ use intern::sym;
use rustc_next_trait_solver::solve::{HasChanged, SolverDelegateEvalExt};
use rustc_type_ir::{
InferCtxtLike, TypingMode,
- inherent::{SliceLike, Span as _},
+ inherent::{SliceLike, Span as _, Ty as _},
solve::Certainty,
};
use span::Edition;
@@ -23,11 +23,11 @@ use crate::{
AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTy,
ProjectionTyExt, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause,
db::HirDatabase,
- infer::unify::InferenceTable,
+ from_assoc_type_id,
next_solver::{
DbInterner, GenericArg, ParamEnv, Predicate, SolverContext, Span,
- infer::{DbInternerInferExt, InferCtxt},
- mapping::{ChalkToNextSolver, convert_canonical_args_for_result},
+ infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause},
+ mapping::{ChalkToNextSolver, NextSolverToChalk, convert_canonical_args_for_result},
util::mini_canonicalize,
},
utils::UnevaluatedConstEvaluatorFolder,
@@ -93,9 +93,30 @@ pub(crate) fn normalize_projection_query<'db>(
return TyKind::Error.intern(Interner);
}
- let mut table = InferenceTable::new(db, env);
- let ty = table.normalize_projection_ty(projection);
- table.resolve_completely(ty)
+ let interner = DbInterner::new_with(db, Some(env.krate), env.block);
+ // FIXME(next-solver): I believe this should use `PostAnalysis` (this is only used for IDE things),
+ // but this causes some bug because of our incorrect impl of `type_of_opaque_hir_typeck()` for TAIT
+ // and async blocks.
+ let infcx = interner.infer_ctxt().build(TypingMode::Analysis {
+ defining_opaque_types_and_generators: crate::next_solver::SolverDefIds::new_from_iter(
+ interner,
+ [],
+ ),
+ });
+ let alias_ty = crate::next_solver::Ty::new_alias(
+ interner,
+ rustc_type_ir::AliasTyKind::Projection,
+ crate::next_solver::AliasTy::new(
+ interner,
+ from_assoc_type_id(projection.associated_ty_id).into(),
+ <crate::Substitution as ChalkToNextSolver<crate::next_solver::GenericArgs<'_>>>::to_nextsolver(&projection.substitution, interner),
+ ),
+ );
+ let mut ctxt = crate::next_solver::obligation_ctxt::ObligationCtxt::new(&infcx);
+ let normalized = ctxt
+ .structurally_normalize_ty(&ObligationCause::dummy(), env.env, alias_ty)
+ .unwrap_or(alias_ty);
+ normalized.replace_infer_with_error(interner).to_chalk(interner)
}
fn identity_subst(
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index fca0162765..c094487a87 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -19,6 +19,7 @@ use hir_ty::{
PathLoweringDiagnostic, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
db::HirDatabase,
diagnostics::{BodyValidationDiagnostic, UnsafetyReason},
+ next_solver::{DbInterner, mapping::NextSolverToChalk},
};
use syntax::{
AstNode, AstPtr, SyntaxError, SyntaxNodePtr, TextRange,
@@ -620,7 +621,7 @@ impl<'db> AnyDiagnostic<'db> {
pub(crate) fn inference_diagnostic(
db: &'db dyn HirDatabase,
def: DefWithBodyId,
- d: &InferenceDiagnostic,
+ d: &InferenceDiagnostic<'db>,
source_map: &hir_def::expr_store::BodySourceMap,
sig_map: &hir_def::expr_store::ExpressionStoreSourceMap,
) -> Option<AnyDiagnostic<'db>> {
@@ -640,6 +641,7 @@ impl<'db> AnyDiagnostic<'db> {
ExprOrPatId::ExprId(expr) => expr_syntax(expr),
ExprOrPatId::PatId(pat) => pat_syntax(pat),
};
+ let interner = DbInterner::new_with(db, None, None);
Some(match d {
&InferenceDiagnostic::NoSuchField { field: expr, private, variant } => {
let expr_or_pat = match expr {
@@ -666,8 +668,11 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::ExpectedFunction { call_expr, found } => {
let call_expr = expr_syntax(*call_expr)?;
- ExpectedFunction { call: call_expr, found: Type::new(db, def, found.clone()) }
- .into()
+ ExpectedFunction {
+ call: call_expr,
+ found: Type::new(db, def, found.to_chalk(interner)),
+ }
+ .into()
}
InferenceDiagnostic::UnresolvedField {
expr,
@@ -679,7 +684,7 @@ impl<'db> AnyDiagnostic<'db> {
UnresolvedField {
expr,
name: name.clone(),
- receiver: Type::new(db, def, receiver.clone()),
+ receiver: Type::new(db, def, receiver.to_chalk(interner)),
method_with_same_name_exists: *method_with_same_name_exists,
}
.into()
@@ -695,10 +700,9 @@ impl<'db> AnyDiagnostic<'db> {
UnresolvedMethodCall {
expr,
name: name.clone(),
- receiver: Type::new(db, def, receiver.clone()),
- field_with_same_name: field_with_same_name
- .clone()
- .map(|ty| Type::new(db, def, ty)),
+ receiver: Type::new(db, def, receiver.to_chalk(interner)),
+ field_with_same_name: (*field_with_same_name)
+ .map(|ty| Type::new(db, def, ty.to_chalk(interner))),
assoc_func_with_same_name: assoc_func_with_same_name.map(Into::into),
}
.into()
@@ -725,7 +729,7 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::TypedHole { expr, expected } => {
let expr = expr_syntax(*expr)?;
- TypedHole { expr, expected: Type::new(db, def, expected.clone()) }.into()
+ TypedHole { expr, expected: Type::new(db, def, expected.to_chalk(interner)) }.into()
}
&InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => {
let expr_or_pat = match pat {
@@ -742,12 +746,13 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::CastToUnsized { expr, cast_ty } => {
let expr = expr_syntax(*expr)?;
- CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.clone()) }.into()
+ CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.to_chalk(interner)) }
+ .into()
}
InferenceDiagnostic::InvalidCast { expr, error, expr_ty, cast_ty } => {
let expr = expr_syntax(*expr)?;
- let expr_ty = Type::new(db, def, expr_ty.clone());
- let cast_ty = Type::new(db, def, cast_ty.clone());
+ let expr_ty = Type::new(db, def, expr_ty.to_chalk(interner));
+ let cast_ty = Type::new(db, def, cast_ty.to_chalk(interner));
InvalidCast { expr, error: *error, expr_ty, cast_ty }.into()
}
InferenceDiagnostic::TyDiagnostic { source, diag } => {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 9198086e9e..d652777711 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -157,7 +157,7 @@ pub use {
tt,
},
hir_ty::{
- CastError, DropGlue, FnAbi, PointerCast, Safety, Variance,
+ CastError, DropGlue, FnAbi, PointerCast, Variance,
consteval::ConstEvalError,
diagnostics::UnsafetyReason,
display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite},
@@ -165,6 +165,7 @@ pub use {
layout::LayoutError,
method_resolution::TyFingerprint,
mir::{MirEvalError, MirLowerError},
+ next_solver::abi::Safety,
},
// FIXME: Properly encapsulate mir
hir_ty::{Interner as ChalkTyInterner, mir},
@@ -1287,9 +1288,11 @@ impl TupleField {
}
pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
+ let interner = DbInterner::new_with(db, None, None);
let ty = db
.infer(self.owner)
.tuple_field_access_type(self.tuple)
+ .to_chalk(interner)
.as_slice(Interner)
.get(self.index as usize)
.and_then(|arg| arg.ty(Interner))
@@ -1720,7 +1723,7 @@ impl Variant {
self.source(db)?.value.expr()
}
- pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError> {
+ pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError<'_>> {
db.const_eval_discriminant(self.into())
}
@@ -2012,6 +2015,7 @@ impl DefWithBody {
style_lints: bool,
) {
let krate = self.module(db).id.krate();
+ let interner = DbInterner::new_with(db, Some(krate), None);
let (body, source_map) = db.body_with_source_map(self.into());
let sig_source_map = match self {
@@ -2061,8 +2065,16 @@ impl DefWithBody {
acc.push(
TypeMismatch {
expr_or_pat,
- expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected.clone()),
- actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual.clone()),
+ expected: Type::new(
+ db,
+ DefWithBodyId::from(self),
+ mismatch.expected.to_chalk(interner),
+ ),
+ actual: Type::new(
+ db,
+ DefWithBodyId::from(self),
+ mismatch.actual.to_chalk(interner),
+ ),
}
.into(),
);
@@ -2628,7 +2640,7 @@ impl Function {
self,
db: &dyn HirDatabase,
span_formatter: impl Fn(FileId, TextRange) -> String,
- ) -> Result<String, ConstEvalError> {
+ ) -> Result<String, ConstEvalError<'_>> {
let body = db.monomorphized_mir_body(
self.id.into(),
Substitution::empty(Interner),
@@ -2912,7 +2924,7 @@ impl Const {
}
/// Evaluate the constant.
- pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError> {
+ pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError<'_>> {
db.const_eval(self.id.into(), Substitution::empty(Interner), None)
.map(|it| EvaluatedConst { const_: it, def: self.id.into() })
}
@@ -2934,7 +2946,7 @@ impl EvaluatedConst {
format!("{}", self.const_.display(db, display_target))
}
- pub fn render_debug(&self, db: &dyn HirDatabase) -> Result<String, MirEvalError> {
+ pub fn render_debug<'db>(&self, db: &'db dyn HirDatabase) -> Result<String, MirEvalError<'db>> {
let data = self.const_.data(Interner);
if let TyKind::Scalar(s) = data.ty.kind(Interner)
&& matches!(s, Scalar::Int(_) | Scalar::Uint(_))
@@ -2990,7 +3002,7 @@ impl Static {
}
/// Evaluate the static initializer.
- pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError> {
+ pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError<'_>> {
db.const_eval(self.id.into(), Substitution::empty(Interner), None)
.map(|it| EvaluatedConst { const_: it, def: self.id.into() })
}
@@ -4021,8 +4033,9 @@ impl Local {
pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
let def = self.parent;
let infer = db.infer(def);
- let ty = infer[self.binding_id].clone();
- Type::new(db, def, ty)
+ let ty = infer[self.binding_id];
+ let interner = DbInterner::new_with(db, None, None);
+ Type::new(db, def, ty.to_chalk(interner))
}
/// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;`
@@ -4466,7 +4479,9 @@ impl Impl {
db: &'db dyn HirDatabase,
Type { ty, env, _pd: _ }: Type<'db>,
) -> Vec<Impl> {
- let def_crates = match method_resolution::def_crates(db, &ty, env.krate) {
+ let interner = DbInterner::new_with(db, None, None);
+ let ty_ns = ty.to_nextsolver(interner);
+ let def_crates = match method_resolution::def_crates(db, ty_ns, env.krate) {
Some(def_crates) => def_crates,
None => return Vec::new(),
};
@@ -4477,7 +4492,7 @@ impl Impl {
ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
};
- let fp = TyFingerprint::for_inherent_impl(&ty);
+ let fp = TyFingerprint::for_inherent_impl(ty_ns);
let fp = match fp {
Some(fp) => fp,
None => return Vec::new(),
@@ -4487,7 +4502,7 @@ impl Impl {
def_crates.iter().for_each(|&id| {
all.extend(
db.inherent_impls_in_crate(id)
- .for_self_ty(&ty)
+ .for_self_ty(ty_ns)
.iter()
.cloned()
.map(Self::from)
@@ -4512,7 +4527,12 @@ impl Impl {
{
if let Some(inherent_impls) = db.inherent_impls_in_block(block) {
all.extend(
- inherent_impls.for_self_ty(&ty).iter().cloned().map(Self::from).filter(filter),
+ inherent_impls
+ .for_self_ty(ty_ns)
+ .iter()
+ .cloned()
+ .map(Self::from)
+ .filter(filter),
);
}
if let Some(trait_impls) = db.trait_impls_in_block(block) {
@@ -4691,10 +4711,10 @@ impl Closure {
.to_string()
}
- pub fn captured_items(&self, db: &dyn HirDatabase) -> Vec<ClosureCapture> {
+ pub fn captured_items<'db>(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> {
let owner = db.lookup_intern_closure((self.id).into()).0;
let infer = &db.infer(owner);
- let info = infer.closure_info(&self.id);
+ let info = infer.closure_info(self.id.into());
info.0
.iter()
.cloned()
@@ -4705,12 +4725,13 @@ impl Closure {
pub fn capture_types<'db>(&self, db: &'db dyn HirDatabase) -> Vec<Type<'db>> {
let owner = db.lookup_intern_closure((self.id).into()).0;
let infer = &db.infer(owner);
- let (captures, _) = infer.closure_info(&self.id);
+ let (captures, _) = infer.closure_info(self.id.into());
+ let interner = DbInterner::new_with(db, None, None);
captures
.iter()
.map(|capture| Type {
env: db.trait_environment_for_body(owner),
- ty: capture.ty(db, &self.subst),
+ ty: capture.ty(db, self.subst.to_nextsolver(interner)).to_chalk(interner),
_pd: PhantomCovariantLifetime::new(),
})
.collect()
@@ -4719,19 +4740,19 @@ impl Closure {
pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait {
let owner = db.lookup_intern_closure((self.id).into()).0;
let infer = &db.infer(owner);
- let info = infer.closure_info(&self.id);
+ let info = infer.closure_info(self.id.into());
info.1
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct ClosureCapture {
+pub struct ClosureCapture<'db> {
owner: DefWithBodyId,
closure: ClosureId,
- capture: hir_ty::CapturedItem,
+ capture: hir_ty::CapturedItem<'db>,
}
-impl ClosureCapture {
+impl<'db> ClosureCapture<'db> {
pub fn local(&self) -> Local {
Local { parent: self.owner, binding_id: self.capture.local() }
}
@@ -5443,7 +5464,8 @@ impl<'db> Type<'db> {
}
pub fn fingerprint_for_trait_impl(&self) -> Option<TyFingerprint> {
- TyFingerprint::for_trait_impl(&self.ty)
+ let interner = DbInterner::conjure();
+ TyFingerprint::for_trait_impl(self.ty.to_nextsolver(interner))
}
pub(crate) fn canonical(&self) -> Canonical<Ty> {
@@ -5487,14 +5509,16 @@ impl<'db> Type<'db> {
krate: Crate,
callback: &mut dyn FnMut(AssocItemId) -> bool,
) {
- let def_crates = match method_resolution::def_crates(db, &self.ty, krate.id) {
+ let interner = DbInterner::new_with(db, None, None);
+ let ty_ns = self.ty.to_nextsolver(interner);
+ let def_crates = match method_resolution::def_crates(db, ty_ns, krate.id) {
Some(it) => it,
None => return,
};
for krate in def_crates {
let impls = db.inherent_impls_in_crate(krate);
- for impl_def in impls.for_self_ty(&self.ty) {
+ for impl_def in impls.for_self_ty(ty_ns) {
for &(_, item) in impl_def.impl_items(db).items.iter() {
if callback(item) {
return;
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 5af8659ca6..45c2020bc8 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -29,6 +29,8 @@ use hir_expand::{
name::AsName,
};
use hir_ty::diagnostics::{unsafe_operations, unsafe_operations_for_body};
+use hir_ty::next_solver::DbInterner;
+use hir_ty::next_solver::mapping::{ChalkToNextSolver, NextSolverToChalk};
use intern::{Interned, Symbol, sym};
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
@@ -1553,19 +1555,24 @@ impl<'db> SemanticsImpl<'db> {
pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjustment<'db>>> {
let mutability = |m| match m {
- hir_ty::Mutability::Not => Mutability::Shared,
- hir_ty::Mutability::Mut => Mutability::Mut,
+ hir_ty::next_solver::Mutability::Not => Mutability::Shared,
+ hir_ty::next_solver::Mutability::Mut => Mutability::Mut,
};
let analyzer = self.analyze(expr.syntax())?;
let (mut source_ty, _) = analyzer.type_of_expr(self.db, expr)?;
+ let interner = DbInterner::new_with(self.db, None, None);
+
analyzer.expr_adjustments(expr).map(|it| {
it.iter()
.map(|adjust| {
- let target =
- Type::new_with_resolver(self.db, &analyzer.resolver, adjust.target.clone());
+ let target = Type::new_with_resolver(
+ self.db,
+ &analyzer.resolver,
+ adjust.target.to_chalk(interner),
+ );
let kind = match adjust.kind {
hir_ty::Adjust::NeverToAny => Adjust::NeverToAny,
hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => {
@@ -1652,11 +1659,18 @@ impl<'db> SemanticsImpl<'db> {
func: Function,
subst: impl IntoIterator<Item = Type<'db>>,
) -> Option<Function> {
- let mut substs = hir_ty::TyBuilder::subst_for_def(self.db, TraitId::from(trait_), None);
- for s in subst {
- substs = substs.push(s.ty);
- }
- Some(self.db.lookup_impl_method(env.env, func.into(), substs.build()).0.into())
+ let interner = DbInterner::new_with(self.db, None, None);
+ let mut subst = subst.into_iter();
+ let substs = hir_ty::next_solver::GenericArgs::for_item(
+ interner,
+ trait_.id.into(),
+ |_, _, id, _| {
+ assert!(matches!(id, hir_def::GenericParamId::TypeParamId(_)), "expected a type");
+ subst.next().expect("too few subst").ty.to_nextsolver(interner).into()
+ },
+ );
+ assert!(subst.next().is_none(), "too many subst");
+ Some(self.db.lookup_impl_method(env.env, func.into(), substs).0.into())
}
fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<StructId> {
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index c6b7e84dc2..5a2849220e 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -18,7 +18,7 @@ use base_db::salsa;
use either::Either;
use hir_def::{
AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId,
- ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StructId, TraitId, VariantId,
+ LocalFieldId, ModuleDefId, StructId, TraitId, VariantId,
expr_store::{
Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId,
lower::ExprCollector,
@@ -36,9 +36,10 @@ use hir_expand::{
mod_path::{ModPath, PathKind, path},
name::{AsName, Name},
};
+use hir_ty::next_solver::GenericArgs;
use hir_ty::{
Adjustment, AliasTy, InferenceResult, Interner, LifetimeElisionKind, ProjectionTy,
- Substitution, ToChalk, TraitEnvironment, Ty, TyExt, TyKind, TyLoweringContext,
+ Substitution, ToChalk, TraitEnvironment, Ty, TyKind, TyLoweringContext,
diagnostics::{
InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields,
unsafe_operations,
@@ -67,16 +68,16 @@ use triomphe::Arc;
pub(crate) struct SourceAnalyzer<'db> {
pub(crate) file_id: HirFileId,
pub(crate) resolver: Resolver<'db>,
- pub(crate) body_or_sig: Option<BodyOrSig>,
+ pub(crate) body_or_sig: Option<BodyOrSig<'db>>,
}
#[derive(Debug)]
-pub(crate) enum BodyOrSig {
+pub(crate) enum BodyOrSig<'db> {
Body {
def: DefWithBodyId,
body: Arc<Body>,
source_map: Arc<BodySourceMap>,
- infer: Option<Arc<InferenceResult>>,
+ infer: Option<Arc<InferenceResult<'db>>>,
},
// To be folded into body once it is considered one
VariantFields {
@@ -116,7 +117,7 @@ impl<'db> SourceAnalyzer<'db> {
def: DefWithBodyId,
node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
offset: Option<TextSize>,
- infer: Option<Arc<InferenceResult>>,
+ infer: Option<Arc<InferenceResult<'db>>>,
) -> SourceAnalyzer<'db> {
let (body, source_map) = db.body_with_source_map(def);
let scopes = db.expr_scopes(def);
@@ -182,7 +183,9 @@ impl<'db> SourceAnalyzer<'db> {
}
// FIXME: Remove this
- fn body_(&self) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult>)> {
+ fn body_(
+ &self,
+ ) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult<'db>>)> {
self.body_or_sig.as_ref().and_then(|it| match it {
BodyOrSig::Body { def, body, source_map, infer } => {
Some((*def, &**body, &**source_map, infer.as_deref()))
@@ -191,7 +194,7 @@ impl<'db> SourceAnalyzer<'db> {
})
}
- fn infer(&self) -> Option<&InferenceResult> {
+ fn infer(&self) -> Option<&InferenceResult<'db>> {
self.body_or_sig.as_ref().and_then(|it| match it {
BodyOrSig::Sig { .. } => None,
BodyOrSig::VariantFields { .. } => None,
@@ -250,7 +253,7 @@ impl<'db> SourceAnalyzer<'db> {
if let Pat::Bind { id, .. } = self.store()?[pat_id.as_pat()?] { Some(id) } else { None }
}
- pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment]> {
+ pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment<'db>]> {
// It is safe to omit destructuring assignments here because they have no adjustments (neither
// expressions nor patterns).
let expr_id = self.expr_id(expr.clone())?.as_expr()?;
@@ -288,9 +291,11 @@ impl<'db> SourceAnalyzer<'db> {
let coerced = expr_id
.as_expr()
.and_then(|expr_id| infer.expr_adjustment(expr_id))
- .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
- let ty = infer[expr_id].clone();
- let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
+ .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target));
+ let ty = infer[expr_id];
+ let mk_ty = |ty: hir_ty::next_solver::Ty<'_>| {
+ Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure()))
+ };
Some((mk_ty(ty), coerced.map(mk_ty)))
}
@@ -311,8 +316,10 @@ impl<'db> SourceAnalyzer<'db> {
}
};
- let ty = infer[expr_or_pat_id].clone();
- let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
+ let ty = infer[expr_or_pat_id];
+ let mk_ty = |ty: hir_ty::next_solver::Ty<'db>| {
+ Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure()))
+ };
Some((mk_ty(ty), coerced.map(mk_ty)))
}
@@ -323,8 +330,10 @@ impl<'db> SourceAnalyzer<'db> {
) -> Option<Type<'db>> {
let binding_id = self.binding_id_of_pat(pat)?;
let infer = self.infer()?;
- let ty = infer[binding_id].clone();
- let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
+ let ty = infer[binding_id];
+ let mk_ty = |ty: hir_ty::next_solver::Ty<'db>| {
+ Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure()))
+ };
Some(mk_ty(ty))
}
@@ -334,8 +343,8 @@ impl<'db> SourceAnalyzer<'db> {
_param: &ast::SelfParam,
) -> Option<Type<'db>> {
let binding = self.body()?.self_param?;
- let ty = self.infer()?[binding].clone();
- Some(Type::new_with_resolver(db, &self.resolver, ty))
+ let ty = self.infer()?[binding];
+ Some(Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure())))
}
pub(crate) fn binding_mode_of_pat(
@@ -347,8 +356,10 @@ impl<'db> SourceAnalyzer<'db> {
let infer = self.infer()?;
infer.binding_mode(id.as_pat()?).map(|bm| match bm {
hir_ty::BindingMode::Move => BindingMode::Move,
- hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut),
- hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => {
+ hir_ty::BindingMode::Ref(hir_ty::next_solver::Mutability::Mut) => {
+ BindingMode::Ref(Mutability::Mut)
+ }
+ hir_ty::BindingMode::Ref(hir_ty::next_solver::Mutability::Not) => {
BindingMode::Ref(Mutability::Shared)
}
})
@@ -364,7 +375,9 @@ impl<'db> SourceAnalyzer<'db> {
infer
.pat_adjustment(pat_id.as_pat()?)?
.iter()
- .map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone()))
+ .map(|ty| {
+ Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure()))
+ })
.collect(),
)
}
@@ -375,9 +388,8 @@ impl<'db> SourceAnalyzer<'db> {
call: &ast::MethodCallExpr,
) -> Option<Callable<'db>> {
let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
- let (func, substs) = self.infer()?.method_resolution(expr_id)?;
+ let (func, args) = self.infer()?.method_resolution(expr_id)?;
let interner = DbInterner::new_with(db, None, None);
- let args: hir_ty::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
let ty = db.value_ty(func.into())?.instantiate(interner, args);
let ty = Type::new_with_resolver(db, &self.resolver, ty.to_chalk(interner));
let mut res = ty.as_callable(db)?;
@@ -403,13 +415,18 @@ impl<'db> SourceAnalyzer<'db> {
) -> Option<(Either<Function, Field>, Option<GenericSubstitution<'db>>)> {
let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
let inference_result = self.infer()?;
+ let interner = DbInterner::new_with(db, None, None);
match inference_result.method_resolution(expr_id) {
Some((f_in_trait, substs)) => {
let (fn_, subst) =
self.resolve_impl_method_or_trait_def_with_subst(db, f_in_trait, substs);
Some((
Either::Left(fn_.into()),
- Some(GenericSubstitution::new(fn_.into(), subst, self.trait_environment(db))),
+ Some(GenericSubstitution::new(
+ fn_.into(),
+ subst.to_chalk(interner),
+ self.trait_environment(db),
+ )),
))
}
None => {
@@ -443,7 +460,7 @@ impl<'db> SourceAnalyzer<'db> {
fn field_subst(
&self,
field_expr: ExprId,
- infer: &InferenceResult,
+ infer: &InferenceResult<'db>,
db: &'db dyn HirDatabase,
) -> Option<GenericSubstitution<'db>> {
let body = self.store()?;
@@ -451,7 +468,7 @@ impl<'db> SourceAnalyzer<'db> {
let (adt, subst) = infer.type_of_expr_with_adjust(object_expr)?.as_adt()?;
return Some(GenericSubstitution::new(
adt.into(),
- subst.clone(),
+ subst.to_chalk(DbInterner::conjure()),
self.trait_environment(db),
));
}
@@ -467,6 +484,7 @@ impl<'db> SourceAnalyzer<'db> {
let (def, ..) = self.body_()?;
let expr_id = self.expr_id(field.clone().into())?.as_expr()?;
let inference_result = self.infer()?;
+ let interner = DbInterner::new_with(db, None, None);
match inference_result.field_resolution(expr_id) {
Some(field) => match field {
Either::Left(field) => Some((
@@ -486,7 +504,11 @@ impl<'db> SourceAnalyzer<'db> {
let (f, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f, substs);
(
Either::Right(f.into()),
- Some(GenericSubstitution::new(f.into(), subst, self.trait_environment(db))),
+ Some(GenericSubstitution::new(
+ f.into(),
+ subst.to_chalk(interner),
+ self.trait_environment(db),
+ )),
)
}),
}
@@ -560,11 +582,11 @@ impl<'db> SourceAnalyzer<'db> {
}
}
- let future_trait = LangItem::Future.resolve_trait(db, self.resolver.krate())?;
let poll_fn = LangItem::FuturePoll.resolve_function(db, self.resolver.krate())?;
// HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself
// doesn't have any generic parameters, so we skip building another subst for `poll()`.
- let substs = hir_ty::TyBuilder::subst_for_def(db, future_trait, None).push(ty).build();
+ let interner = DbInterner::new_with(db, None, None);
+ let substs = GenericArgs::new_from_iter(interner, [ty.to_nextsolver(interner).into()]);
Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs))
}
@@ -573,7 +595,7 @@ impl<'db> SourceAnalyzer<'db> {
db: &'db dyn HirDatabase,
prefix_expr: &ast::PrefixExpr,
) -> Option<FunctionId> {
- let (op_trait, op_fn) = match prefix_expr.op_kind()? {
+ let (_op_trait, op_fn) = match prefix_expr.op_kind()? {
ast::UnaryOp::Deref => {
// This can be either `Deref::deref` or `DerefMut::deref_mut`.
// Since deref kind is inferenced and stored in `InferenceResult.method_resolution`,
@@ -603,9 +625,10 @@ impl<'db> SourceAnalyzer<'db> {
let ty = self.ty_of_expr(prefix_expr.expr()?)?;
+ let interner = DbInterner::new_with(db, None, None);
// HACK: subst for all methods coincides with that for their trait because the methods
// don't have any generic parameters, so we skip building another subst for the methods.
- let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build();
+ let substs = GenericArgs::new_from_iter(interner, [ty.to_nextsolver(interner).into()]);
Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
}
@@ -618,27 +641,28 @@ impl<'db> SourceAnalyzer<'db> {
let base_ty = self.ty_of_expr(index_expr.base()?)?;
let index_ty = self.ty_of_expr(index_expr.index()?)?;
- let (index_trait, index_fn) =
+ let (_index_trait, index_fn) =
self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index))?;
- let (op_trait, op_fn) = self
+ let op_fn = self
.infer()
.and_then(|infer| {
let expr = self.expr_id(index_expr.clone().into())?.as_expr()?;
let (func, _) = infer.method_resolution(expr)?;
- let (index_mut_trait, index_mut_fn) = self.lang_trait_fn(
+ let (_index_mut_trait, index_mut_fn) = self.lang_trait_fn(
db,
LangItem::IndexMut,
&Name::new_symbol_root(sym::index_mut),
)?;
- if func == index_mut_fn { Some((index_mut_trait, index_mut_fn)) } else { None }
+ if func == index_mut_fn { Some(index_mut_fn) } else { None }
})
- .unwrap_or((index_trait, index_fn));
+ .unwrap_or(index_fn);
// HACK: subst for all methods coincides with that for their trait because the methods
// don't have any generic parameters, so we skip building another subst for the methods.
- let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None)
- .push(base_ty.clone())
- .push(index_ty.clone())
- .build();
+ let interner = DbInterner::new_with(db, None, None);
+ let substs = GenericArgs::new_from_iter(
+ interner,
+ [base_ty.to_nextsolver(interner).into(), index_ty.to_nextsolver(interner).into()],
+ );
Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
}
@@ -651,14 +675,15 @@ impl<'db> SourceAnalyzer<'db> {
let lhs = self.ty_of_expr(binop_expr.lhs()?)?;
let rhs = self.ty_of_expr(binop_expr.rhs()?)?;
- let (op_trait, op_fn) = lang_items_for_bin_op(op)
+ let (_op_trait, op_fn) = lang_items_for_bin_op(op)
.and_then(|(name, lang_item)| self.lang_trait_fn(db, lang_item, &name))?;
// HACK: subst for `index()` coincides with that for `Index` because `index()` itself
// doesn't have any generic parameters, so we skip building another subst for `index()`.
- let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None)
- .push(lhs.clone())
- .push(rhs.clone())
- .build();
+ let interner = DbInterner::new_with(db, None, None);
+ let substs = GenericArgs::new_from_iter(
+ interner,
+ [lhs.to_nextsolver(interner).into(), rhs.to_nextsolver(interner).into()],
+ );
Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
}
@@ -671,13 +696,10 @@ impl<'db> SourceAnalyzer<'db> {
let ty = self.ty_of_expr(try_expr.expr()?)?;
let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?;
- let op_trait = match op_fn.lookup(db).container {
- ItemContainerId::TraitId(id) => id,
- _ => return None,
- };
// HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself
// doesn't have any generic parameters, so we skip building another subst for `branch()`.
- let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build();
+ let interner = DbInterner::new_with(db, None, None);
+ let substs = GenericArgs::new_from_iter(interner, [ty.to_nextsolver(interner).into()]);
Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
}
@@ -690,6 +712,7 @@ impl<'db> SourceAnalyzer<'db> {
let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
let expr = ast::Expr::from(record_expr);
let expr_id = self.store_sm()?.node_expr(InFile::new(self.file_id, &expr))?;
+ let interner = DbInterner::new_with(db, None, None);
let ast_name = field.field_name()?;
let local_name = ast_name.as_name();
@@ -713,16 +736,17 @@ impl<'db> SourceAnalyzer<'db> {
}
};
let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
+ let subst = subst.to_chalk(interner);
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(variant).get(field.local_id)?.clone().substitute(Interner, subst);
+ db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, &subst);
Some((
field.into(),
local,
Type::new_with_resolver(db, &self.resolver, field_ty),
- GenericSubstitution::new(adt.into(), subst.clone(), self.trait_environment(db)),
+ GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)),
))
}
@@ -731,6 +755,7 @@ impl<'db> SourceAnalyzer<'db> {
db: &'db dyn HirDatabase,
field: &ast::RecordPatField,
) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> {
+ let interner = DbInterner::new_with(db, None, None);
let field_name = field.field_name()?.as_name();
let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
let pat_id = self.pat_id(&record_pat.into())?;
@@ -738,12 +763,13 @@ 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 subst = subst.to_chalk(interner);
let field_ty =
- db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
+ db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, &subst);
Some((
field.into(),
Type::new_with_resolver(db, &self.resolver, field_ty),
- GenericSubstitution::new(adt.into(), subst.clone(), self.trait_environment(db)),
+ GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)),
))
}
@@ -859,6 +885,7 @@ impl<'db> SourceAnalyzer<'db> {
db: &'db dyn HirDatabase,
path: &ast::Path,
) -> Option<(PathResolution, Option<GenericSubstitution<'db>>)> {
+ let interner = DbInterner::new_with(db, None, None);
let parent = path.syntax().parent();
let parent = || parent.clone();
@@ -874,29 +901,31 @@ impl<'db> SourceAnalyzer<'db> {
None => {
let subst = GenericSubstitution::new(
f_in_trait.into(),
- subs,
+ subs.to_chalk(interner),
self.trait_environment(db),
);
(assoc, subst)
}
Some(func_ty) => {
- if let TyKind::FnDef(_fn_def, subs) = func_ty.kind(Interner) {
+ if let TyKind::FnDef(_fn_def, subs) =
+ func_ty.to_chalk(interner).kind(Interner)
+ {
let (fn_, subst) = self
.resolve_impl_method_or_trait_def_with_subst(
db,
f_in_trait,
- subs.clone(),
+ subs.to_nextsolver(interner),
);
let subst = GenericSubstitution::new(
fn_.into(),
- subst,
+ subst.to_chalk(interner),
self.trait_environment(db),
);
(fn_.into(), subst)
} else {
let subst = GenericSubstitution::new(
f_in_trait.into(),
- subs,
+ subs.to_chalk(interner),
self.trait_environment(db),
);
(assoc, subst)
@@ -909,7 +938,7 @@ impl<'db> SourceAnalyzer<'db> {
self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
let subst = GenericSubstitution::new(
konst.into(),
- subst,
+ subst.to_chalk(interner),
self.trait_environment(db),
);
(konst.into(), subst)
@@ -918,7 +947,7 @@ impl<'db> SourceAnalyzer<'db> {
assoc,
GenericSubstitution::new(
type_alias.into(),
- subs,
+ subs.to_chalk(interner),
self.trait_environment(db),
),
),
@@ -942,7 +971,7 @@ impl<'db> SourceAnalyzer<'db> {
self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
let subst = GenericSubstitution::new(
konst.into(),
- subst,
+ subst.to_chalk(interner),
self.trait_environment(db),
);
(konst.into(), subst)
@@ -951,7 +980,7 @@ impl<'db> SourceAnalyzer<'db> {
assoc,
GenericSubstitution::new(
assoc.into(),
- subs,
+ subs.to_chalk(interner),
self.trait_environment(db),
),
),
@@ -1149,10 +1178,10 @@ impl<'db> SourceAnalyzer<'db> {
let parent = parent()?;
let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) {
let expr_id = self.expr_id(expr)?;
- self.infer()?.type_of_expr_or_pat(expr_id)?
+ self.infer()?.type_of_expr_or_pat(expr_id)?.to_chalk(interner)
} else if let Some(pat) = ast::Pat::cast(parent) {
let pat_id = self.pat_id(&pat)?;
- &self.infer()?[pat_id]
+ self.infer()?[pat_id].to_chalk(interner)
} else {
return None;
};
@@ -1232,7 +1261,8 @@ impl<'db> SourceAnalyzer<'db> {
record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?
}
};
- let res = self.missing_fields(db, substs, variant, missing_fields);
+ let interner = DbInterner::new_with(db, None, None);
+ let res = self.missing_fields(db, &substs.to_chalk(interner), variant, missing_fields);
Some(res)
}
@@ -1249,7 +1279,8 @@ impl<'db> SourceAnalyzer<'db> {
let (variant, missing_fields, _exhaustive) =
record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
- let res = self.missing_fields(db, substs, variant, missing_fields);
+ let interner = DbInterner::new_with(db, None, None);
+ let res = self.missing_fields(db, &substs.to_chalk(interner), variant, missing_fields);
Some(res)
}
@@ -1379,7 +1410,7 @@ impl<'db> SourceAnalyzer<'db> {
&self,
db: &'db dyn HirDatabase,
func: FunctionId,
- substs: Substitution,
+ substs: GenericArgs<'db>,
) -> FunctionId {
self.resolve_impl_method_or_trait_def_with_subst(db, func, substs).0
}
@@ -1388,8 +1419,8 @@ impl<'db> SourceAnalyzer<'db> {
&self,
db: &'db dyn HirDatabase,
func: FunctionId,
- substs: Substitution,
- ) -> (FunctionId, Substitution) {
+ substs: GenericArgs<'db>,
+ ) -> (FunctionId, GenericArgs<'db>) {
let owner = match self.resolver.body_owner() {
Some(it) => it,
None => return (func, substs),
@@ -1402,14 +1433,19 @@ impl<'db> SourceAnalyzer<'db> {
&self,
db: &'db dyn HirDatabase,
const_id: ConstId,
- subs: Substitution,
- ) -> (ConstId, Substitution) {
+ subs: GenericArgs<'db>,
+ ) -> (ConstId, GenericArgs<'db>) {
let owner = match self.resolver.body_owner() {
Some(it) => it,
None => return (const_id, subs),
};
let env = db.trait_environment_for_body(owner);
- method_resolution::lookup_impl_const(db, env, const_id, subs)
+ method_resolution::lookup_impl_const(
+ DbInterner::new_with(db, None, None),
+ env,
+ const_id,
+ subs,
+ )
}
fn lang_trait_fn(
@@ -1423,8 +1459,10 @@ impl<'db> SourceAnalyzer<'db> {
Some((trait_id, fn_id))
}
- fn ty_of_expr(&self, expr: ast::Expr) -> Option<&Ty> {
- self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?)
+ fn ty_of_expr(&self, expr: ast::Expr) -> Option<Ty> {
+ self.infer()?
+ .type_of_expr_or_pat(self.expr_id(expr)?)
+ .map(|ty| ty.to_chalk(DbInterner::conjure()))
}
}
diff --git a/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
index 3dd435d942..2cda6d6f1c 100644
--- a/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
+++ b/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
@@ -506,7 +506,7 @@ fn wrap_capture_in_deref_if_needed(
make::expr_prefix(T![*], capture_name).into()
}
-fn capture_as_arg(ctx: &AssistContext<'_>, capture: &ClosureCapture) -> ast::Expr {
+fn capture_as_arg(ctx: &AssistContext<'_>, capture: &ClosureCapture<'_>) -> ast::Expr {
let place = parse_expr_from_str(&capture.display_place_source_code(ctx.db()), ctx.edition())
.expect("`display_place_source_code()` produced an invalid expr");
let needs_mut = match capture.kind() {
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index dbf68dbe33..094e679501 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -2987,7 +2987,6 @@ fn main() {
&[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
expect![[r#"
sn not !expr [snippet]
- me not() fn(self) -> <Self as Not>::Output [type_could_unify+requires_import]
sn box Box::new(expr) []
sn call function(expr) []
sn const const {} []
@@ -3001,6 +3000,7 @@ fn main() {
sn return return expr []
sn unsafe unsafe {} []
sn while while expr {} []
+ me not() fn(self) -> <Self as Not>::Output [requires_import]
"#]],
);
}
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 8613581292..e6702ccf13 100644
--- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -1170,7 +1170,7 @@ trait B {}
fn test(a: &dyn A) -> &dyn B {
a
- //^ error: expected &dyn B, found &dyn A
+ //^ error: expected &(dyn B + 'static), found &(dyn A + 'static)
}
"#,
);
diff --git a/crates/ide-ssr/src/matching.rs b/crates/ide-ssr/src/matching.rs
index 595f0bb5fa..9c0b9a6ff9 100644
--- a/crates/ide-ssr/src/matching.rs
+++ b/crates/ide-ssr/src/matching.rs
@@ -791,6 +791,8 @@ impl PatternIterator {
#[cfg(test)]
mod tests {
+ use ide_db::base_db::salsa;
+
use crate::{MatchFinder, SsrRule};
#[test]
@@ -799,33 +801,35 @@ mod tests {
let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }";
let (db, position, selections) = crate::tests::single_file(input);
- let position = ide_db::FilePosition {
- file_id: position.file_id.file_id(&db),
- offset: position.offset,
- };
- let mut match_finder = MatchFinder::in_context(
- &db,
- position,
- selections
- .into_iter()
- .map(|frange| ide_db::FileRange {
- file_id: frange.file_id.file_id(&db),
- range: frange.range,
- })
- .collect(),
- )
- .unwrap();
- match_finder.add_rule(rule).unwrap();
- let matches = match_finder.matches();
- assert_eq!(matches.matches.len(), 1);
- assert_eq!(matches.matches[0].matched_node.text(), "foo(1+2)");
- assert_eq!(matches.matches[0].placeholder_values.len(), 1);
-
- let edits = match_finder.edits();
- assert_eq!(edits.len(), 1);
- let edit = &edits[&position.file_id];
- let mut after = input.to_owned();
- edit.apply(&mut after);
- assert_eq!(after, "fn foo() {} fn bar() {} fn main() { bar(1+2); }");
+ salsa::attach(&db, || {
+ let position = ide_db::FilePosition {
+ file_id: position.file_id.file_id(&db),
+ offset: position.offset,
+ };
+ let mut match_finder = MatchFinder::in_context(
+ &db,
+ position,
+ selections
+ .into_iter()
+ .map(|frange| ide_db::FileRange {
+ file_id: frange.file_id.file_id(&db),
+ range: frange.range,
+ })
+ .collect(),
+ )
+ .unwrap();
+ match_finder.add_rule(rule).unwrap();
+ let matches = match_finder.matches();
+ assert_eq!(matches.matches.len(), 1);
+ assert_eq!(matches.matches[0].matched_node.text(), "foo(1+2)");
+ assert_eq!(matches.matches[0].placeholder_values.len(), 1);
+
+ let edits = match_finder.edits();
+ assert_eq!(edits.len(), 1);
+ let edit = &edits[&position.file_id];
+ let mut after = input.to_owned();
+ edit.apply(&mut after);
+ assert_eq!(after, "fn foo() {} fn bar() {} fn main() { bar(1+2); }");
+ });
}
}
diff --git a/crates/ide-ssr/src/tests.rs b/crates/ide-ssr/src/tests.rs
index 875b4d9b06..24ad3ba7ef 100644
--- a/crates/ide-ssr/src/tests.rs
+++ b/crates/ide-ssr/src/tests.rs
@@ -101,33 +101,37 @@ fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) {
fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
let (db, position, selections) = single_file(input);
- let position =
- ide_db::FilePosition { file_id: position.file_id.file_id(&db), offset: position.offset };
- let mut match_finder = MatchFinder::in_context(
- &db,
- position,
- selections
- .into_iter()
- .map(|selection| ide_db::FileRange {
- file_id: selection.file_id.file_id(&db),
- range: selection.range,
- })
- .collect(),
- )
- .unwrap();
- for rule in rules {
- let rule: SsrRule = rule.parse().unwrap();
- match_finder.add_rule(rule).unwrap();
- }
- let edits = salsa::attach(&db, || match_finder.edits());
- if edits.is_empty() {
- panic!("No edits were made");
- }
- // Note, db.file_text is not necessarily the same as `input`, since fixture parsing alters
- // stuff.
- let mut actual = db.file_text(position.file_id).text(&db).to_string();
- edits[&position.file_id].apply(&mut actual);
- expected.assert_eq(&actual);
+ salsa::attach(&db, || {
+ let position = ide_db::FilePosition {
+ file_id: position.file_id.file_id(&db),
+ offset: position.offset,
+ };
+ let mut match_finder = MatchFinder::in_context(
+ &db,
+ position,
+ selections
+ .into_iter()
+ .map(|selection| ide_db::FileRange {
+ file_id: selection.file_id.file_id(&db),
+ range: selection.range,
+ })
+ .collect(),
+ )
+ .unwrap();
+ for rule in rules {
+ let rule: SsrRule = rule.parse().unwrap();
+ match_finder.add_rule(rule).unwrap();
+ }
+ let edits = match_finder.edits();
+ if edits.is_empty() {
+ panic!("No edits were made");
+ }
+ // Note, db.file_text is not necessarily the same as `input`, since fixture parsing alters
+ // stuff.
+ let mut actual = db.file_text(position.file_id).text(&db).to_string();
+ edits[&position.file_id].apply(&mut actual);
+ expected.assert_eq(&actual);
+ })
}
#[allow(clippy::print_stdout)]
@@ -145,51 +149,57 @@ fn print_match_debug_info(match_finder: &MatchFinder<'_>, file_id: EditionedFile
fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
let (db, position, selections) = single_file(code);
- let mut match_finder = MatchFinder::in_context(
- &db,
- ide_db::FilePosition { file_id: position.file_id.file_id(&db), offset: position.offset },
- selections
- .into_iter()
- .map(|selection| ide_db::FileRange {
- file_id: selection.file_id.file_id(&db),
- range: selection.range,
- })
- .collect(),
- )
- .unwrap();
- match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
- let matched_strings: Vec<String> = salsa::attach(&db, || match_finder.matches())
- .flattened()
- .matches
- .iter()
- .map(|m| m.matched_text())
- .collect();
- if matched_strings != expected && !expected.is_empty() {
- print_match_debug_info(&match_finder, position.file_id, expected[0]);
- }
- assert_eq!(matched_strings, expected);
+ salsa::attach(&db, || {
+ let mut match_finder = MatchFinder::in_context(
+ &db,
+ ide_db::FilePosition {
+ file_id: position.file_id.file_id(&db),
+ offset: position.offset,
+ },
+ selections
+ .into_iter()
+ .map(|selection| ide_db::FileRange {
+ file_id: selection.file_id.file_id(&db),
+ range: selection.range,
+ })
+ .collect(),
+ )
+ .unwrap();
+ match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
+ let matched_strings: Vec<String> =
+ match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect();
+ if matched_strings != expected && !expected.is_empty() {
+ print_match_debug_info(&match_finder, position.file_id, expected[0]);
+ }
+ assert_eq!(matched_strings, expected);
+ })
}
fn assert_no_match(pattern: &str, code: &str) {
let (db, position, selections) = single_file(code);
- let mut match_finder = MatchFinder::in_context(
- &db,
- ide_db::FilePosition { file_id: position.file_id.file_id(&db), offset: position.offset },
- selections
- .into_iter()
- .map(|selection| ide_db::FileRange {
- file_id: selection.file_id.file_id(&db),
- range: selection.range,
- })
- .collect(),
- )
- .unwrap();
- match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
- let matches = match_finder.matches().flattened().matches;
- if !matches.is_empty() {
- print_match_debug_info(&match_finder, position.file_id, &matches[0].matched_text());
- panic!("Got {} matches when we expected none: {matches:#?}", matches.len());
- }
+ salsa::attach(&db, || {
+ let mut match_finder = MatchFinder::in_context(
+ &db,
+ ide_db::FilePosition {
+ file_id: position.file_id.file_id(&db),
+ offset: position.offset,
+ },
+ selections
+ .into_iter()
+ .map(|selection| ide_db::FileRange {
+ file_id: selection.file_id.file_id(&db),
+ range: selection.range,
+ })
+ .collect(),
+ )
+ .unwrap();
+ match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
+ let matches = match_finder.matches().flattened().matches;
+ if !matches.is_empty() {
+ print_match_debug_info(&match_finder, position.file_id, &matches[0].matched_text());
+ panic!("Got {} matches when we expected none: {matches:#?}", matches.len());
+ }
+ });
}
fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) {
diff --git a/crates/ide/src/inlay_hints/bind_pat.rs b/crates/ide/src/inlay_hints/bind_pat.rs
index b7c1241396..121b16b97e 100644
--- a/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/crates/ide/src/inlay_hints/bind_pat.rs
@@ -646,9 +646,9 @@ auto trait Sync {}
fn main() {
// The block expression wrapping disables the constructor hint hiding logic
let _v = { Vec::<Box<&(dyn Display + Sync)>>::new() };
- //^^ Vec<Box<&(dyn Display + Sync)>>
+ //^^ Vec<Box<&(dyn Display + Sync + 'static)>>
let _v = { Vec::<Box<*const (dyn Display + Sync)>>::new() };
- //^^ Vec<Box<*const (dyn Display + Sync)>>
+ //^^ Vec<Box<*const (dyn Display + Sync + 'static)>>
let _v = { Vec::<Box<dyn Display + Sync + 'static>>::new() };
//^^ Vec<Box<dyn Display + Sync + 'static>>
}
diff --git a/crates/ide/src/interpret.rs b/crates/ide/src/interpret.rs
index 8f9d2d6bf1..05cd145033 100644
--- a/crates/ide/src/interpret.rs
+++ b/crates/ide/src/interpret.rs
@@ -60,7 +60,7 @@ fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Dura
pub(crate) fn render_const_eval_error(
db: &RootDatabase,
- e: ConstEvalError,
+ e: ConstEvalError<'_>,
display_target: DisplayTarget,
) -> String {
let span_formatter = |file_id, text_range: TextRange| {
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index 9911b85799..3f3d36bde2 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -228,32 +228,30 @@ impl StaticIndex<'_> {
let id = if let Some(it) = self.def_map.get(&def) {
*it
} else {
- let it = salsa::attach(sema.db, || {
- self.tokens.insert(TokenStaticData {
- documentation: documentation_for_definition(&sema, def, scope_node),
- hover: Some(hover_for_definition(
- &sema,
- file_id,
- def,
- None,
- scope_node,
- None,
- false,
- &hover_config,
- edition,
- display_target,
- )),
- definition: def.try_to_nav(&sema).map(UpmappingResult::call_site).map(
- |it| FileRange { file_id: it.file_id, range: it.focus_or_full_range() },
- ),
- references: vec![],
- moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)),
- display_name: def
- .name(self.db)
- .map(|name| name.display(self.db, edition).to_string()),
- signature: Some(def.label(self.db, display_target)),
- kind: def_to_kind(self.db, def),
- })
+ let it = self.tokens.insert(TokenStaticData {
+ documentation: documentation_for_definition(&sema, def, scope_node),
+ hover: Some(hover_for_definition(
+ &sema,
+ file_id,
+ def,
+ None,
+ scope_node,
+ None,
+ false,
+ &hover_config,
+ edition,
+ display_target,
+ )),
+ definition: def.try_to_nav(&sema).map(UpmappingResult::call_site).map(|it| {
+ FileRange { file_id: it.file_id, range: it.focus_or_full_range() }
+ }),
+ references: vec![],
+ moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)),
+ display_name: def
+ .name(self.db)
+ .map(|name| name.display(self.db, edition).to_string()),
+ signature: Some(def.label(self.db, display_target)),
+ kind: def_to_kind(self.db, def),
});
self.def_map.insert(def, it);
it
@@ -295,37 +293,40 @@ impl StaticIndex<'_> {
vendored_libs_config: VendoredLibrariesConfig<'_>,
) -> StaticIndex<'a> {
let db = &analysis.db;
- let work = all_modules(db).into_iter().filter(|module| {
- let file_id = module.definition_source_file_id(db).original_file(db);
- let source_root = db.file_source_root(file_id.file_id(&analysis.db)).source_root_id(db);
- let source_root = db.source_root(source_root).source_root(db);
- let is_vendored = match vendored_libs_config {
- VendoredLibrariesConfig::Included { workspace_root } => source_root
- .path_for_file(&file_id.file_id(&analysis.db))
- .is_some_and(|module_path| module_path.starts_with(workspace_root)),
- VendoredLibrariesConfig::Excluded => false,
+ salsa::attach(db, || {
+ let work = all_modules(db).into_iter().filter(|module| {
+ let file_id = module.definition_source_file_id(db).original_file(db);
+ let source_root =
+ db.file_source_root(file_id.file_id(&analysis.db)).source_root_id(db);
+ let source_root = db.source_root(source_root).source_root(db);
+ let is_vendored = match vendored_libs_config {
+ VendoredLibrariesConfig::Included { workspace_root } => source_root
+ .path_for_file(&file_id.file_id(&analysis.db))
+ .is_some_and(|module_path| module_path.starts_with(workspace_root)),
+ VendoredLibrariesConfig::Excluded => false,
+ };
+
+ !source_root.is_library || is_vendored
+ });
+ let mut this = StaticIndex {
+ files: vec![],
+ tokens: Default::default(),
+ analysis,
+ db,
+ def_map: Default::default(),
};
-
- !source_root.is_library || is_vendored
- });
- let mut this = StaticIndex {
- files: vec![],
- tokens: Default::default(),
- analysis,
- db,
- def_map: Default::default(),
- };
- let mut visited_files = FxHashSet::default();
- for module in work {
- let file_id = module.definition_source_file_id(db).original_file(db);
- if visited_files.contains(&file_id) {
- continue;
+ let mut visited_files = FxHashSet::default();
+ for module in work {
+ let file_id = module.definition_source_file_id(db).original_file(db);
+ if visited_files.contains(&file_id) {
+ continue;
+ }
+ this.add_file(file_id.file_id(&analysis.db));
+ // mark the file
+ visited_files.insert(file_id);
}
- this.add_file(file_id.file_id(&analysis.db));
- // mark the file
- visited_files.insert(file_id);
- }
- this
+ this
+ })
}
}
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 4e43387f8d..720183ac54 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -426,9 +426,12 @@ fn traverse(
let edition = descended_element.file_id.edition(sema.db);
let (unsafe_ops, bindings_shadow_count) = match current_body {
Some(current_body) => {
- let (ops, bindings) = per_body_cache
- .entry(current_body)
- .or_insert_with(|| (sema.get_unsafe_ops(current_body), Default::default()));
+ let (ops, bindings) = per_body_cache.entry(current_body).or_insert_with(|| {
+ (
+ salsa::attach(sema.db, || sema.get_unsafe_ops(current_body)),
+ Default::default(),
+ )
+ });
(&*ops, Some(bindings))
}
None => (&empty, None),
diff --git a/crates/ide/src/view_memory_layout.rs b/crates/ide/src/view_memory_layout.rs
index ddd58a0a3c..b014261981 100644
--- a/crates/ide/src/view_memory_layout.rs
+++ b/crates/ide/src/view_memory_layout.rs
@@ -3,7 +3,6 @@ use std::fmt;
use hir::{DisplayTarget, Field, HirDisplay, Layout, Semantics, Type};
use ide_db::{
RootDatabase,
- base_db::salsa,
defs::Definition,
helpers::{get_definition, pick_best_token},
};
@@ -94,14 +93,14 @@ pub(crate) fn view_memory_layout(
let def = get_definition(&sema, token)?;
let ty = match def {
- Definition::Adt(it) => salsa::attach(db, || it.ty(db)),
- Definition::TypeAlias(it) => salsa::attach(db, || it.ty(db)),
+ Definition::Adt(it) => it.ty(db),
+ Definition::TypeAlias(it) => it.ty(db),
Definition::BuiltinType(it) => it.ty(db),
Definition::SelfType(it) => it.self_ty(db),
Definition::Local(it) => it.ty(db),
- Definition::Field(it) => salsa::attach(db, || it.ty(db).to_type(db)),
- Definition::Const(it) => salsa::attach(db, || it.ty(db)),
- Definition::Static(it) => salsa::attach(db, || it.ty(db)),
+ Definition::Field(it) => it.ty(db).to_type(db),
+ Definition::Const(it) => it.ty(db),
+ Definition::Static(it) => it.ty(db),
_ => return None,
};
@@ -139,12 +138,10 @@ pub(crate) fn view_memory_layout(
nodes[parent_idx].children_len = fields.len() as u64;
for (field, child_ty) in fields.iter() {
- if let Ok(child_layout) = salsa::attach(db, || child_ty.layout(db)) {
+ if let Ok(child_layout) = child_ty.layout(db) {
nodes.push(MemoryLayoutNode {
item_name: field.name(db),
- typename: salsa::attach(db, || {
- child_ty.display(db, display_target).to_string()
- }),
+ typename: { child_ty.display(db, display_target).to_string() },
size: child_layout.size(),
alignment: child_layout.align(),
offset: match *field {
@@ -172,13 +169,13 @@ pub(crate) fn view_memory_layout(
}
for (i, (_, child_ty)) in fields.iter().enumerate() {
- if let Ok(child_layout) = salsa::attach(db, || child_ty.layout(db)) {
+ if let Ok(child_layout) = child_ty.layout(db) {
read_layout(nodes, db, child_ty, &child_layout, children_start + i, display_target);
}
}
}
- salsa::attach(db, || ty.layout(db))
+ ty.layout(db)
.map(|layout| {
let item_name = match def {
// def is a datatype
@@ -191,7 +188,7 @@ pub(crate) fn view_memory_layout(
def => def.name(db).map(|n| n.as_str().to_owned()).unwrap_or("[ROOT]".to_owned()),
};
- let typename = salsa::attach(db, || ty.display(db, display_target).to_string());
+ let typename = ty.display(db, display_target).to_string();
let mut nodes = vec![MemoryLayoutNode {
item_name,
@@ -216,13 +213,14 @@ mod tests {
use crate::fixture;
use expect_test::expect;
+ use ide_db::base_db::salsa;
fn make_memory_layout(
#[rust_analyzer::rust_fixture] ra_fixture: &str,
) -> Option<RecursiveMemoryLayout> {
let (analysis, position, _) = fixture::annotations(ra_fixture);
- view_memory_layout(&analysis.db, position)
+ salsa::attach(&analysis.db, || view_memory_layout(&analysis.db, position))
}
#[test]
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index b301a7189b..c746f848b6 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -75,6 +75,8 @@ vfs-notify.workspace = true
vfs.workspace = true
paths.workspace = true
+ra-ap-rustc_type_ir.workspace = true
+
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.60", features = [
"Win32_System_Diagnostics_Debug",
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 9551536cf4..9c87435368 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -20,14 +20,16 @@ use hir_def::{
expr_store::BodySourceMap,
hir::{ExprId, PatId},
};
-use hir_ty::{Interner, TyExt, TypeFlags};
use ide::{
Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, Edition, InlayFieldsToResolve,
InlayHintsConfig, LineCol, RootDatabase,
};
use ide_db::{
EditionedFileId, LineIndexDatabase, SnippetCap,
- base_db::{SourceDatabase, salsa::Database},
+ base_db::{
+ SourceDatabase,
+ salsa::{self, Database},
+ },
};
use itertools::Itertools;
use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace};
@@ -36,6 +38,7 @@ use profile::StopWatch;
use project_model::{CargoConfig, CfgOverrides, ProjectManifest, ProjectWorkspace, RustLibSource};
use rayon::prelude::*;
use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_type_ir::inherent::Ty as _;
use syntax::AstNode;
use vfs::{AbsPathBuf, Vfs, VfsPath};
@@ -312,33 +315,35 @@ impl flags::AnalysisStats {
shuffle(&mut rng, &mut bodies);
}
- if !self.skip_lowering {
- self.run_body_lowering(db, &vfs, &bodies, verbosity);
- }
+ salsa::attach(db, || {
+ if !self.skip_lowering {
+ self.run_body_lowering(db, &vfs, &bodies, verbosity);
+ }
- if !self.skip_inference {
- self.run_inference(db, &vfs, &bodies, verbosity);
- }
+ if !self.skip_inference {
+ self.run_inference(db, &vfs, &bodies, verbosity);
+ }
- if !self.skip_mir_stats {
- self.run_mir_lowering(db, &bodies, verbosity);
- }
+ if !self.skip_mir_stats {
+ self.run_mir_lowering(db, &bodies, verbosity);
+ }
- if !self.skip_data_layout {
- self.run_data_layout(db, &adts, verbosity);
- }
+ if !self.skip_data_layout {
+ self.run_data_layout(db, &adts, verbosity);
+ }
- if !self.skip_const_eval {
- self.run_const_eval(db, &bodies, verbosity);
- }
+ if !self.skip_const_eval {
+ self.run_const_eval(db, &bodies, verbosity);
+ }
- if self.run_all_ide_things {
- self.run_ide_things(host.analysis(), file_ids.clone(), db, &vfs, verbosity);
- }
+ if self.run_all_ide_things {
+ self.run_ide_things(host.analysis(), file_ids.clone(), db, &vfs, verbosity);
+ }
- if self.run_term_search {
- self.run_term_search(&workspace, db, &vfs, file_ids, verbosity);
- }
+ if self.run_term_search {
+ self.run_term_search(&workspace, db, &vfs, file_ids, verbosity);
+ }
+ });
let db = host.raw_database_mut();
db.trigger_lru_eviction();
@@ -814,7 +819,7 @@ impl flags::AnalysisStats {
for (expr_id, _) in body.exprs() {
let ty = &inference_result[expr_id];
num_exprs += 1;
- let unknown_or_partial = if ty.is_unknown() {
+ let unknown_or_partial = if ty.is_ty_error() {
num_exprs_unknown += 1;
if verbosity.is_spammy() {
if let Some((path, start, end)) = expr_syntax_range(db, vfs, &sm(), expr_id)
@@ -836,8 +841,7 @@ impl flags::AnalysisStats {
}
true
} else {
- let is_partially_unknown =
- ty.data(Interner).flags.contains(TypeFlags::HAS_ERROR);
+ let is_partially_unknown = ty.references_non_lt_error();
if is_partially_unknown {
num_exprs_partially_unknown += 1;
}
@@ -919,7 +923,7 @@ impl flags::AnalysisStats {
for (pat_id, _) in body.pats() {
let ty = &inference_result[pat_id];
num_pats += 1;
- let unknown_or_partial = if ty.is_unknown() {
+ let unknown_or_partial = if ty.is_ty_error() {
num_pats_unknown += 1;
if verbosity.is_spammy() {
if let Some((path, start, end)) = pat_syntax_range(db, vfs, &sm(), pat_id) {
@@ -940,8 +944,7 @@ impl flags::AnalysisStats {
}
true
} else {
- let is_partially_unknown =
- ty.data(Interner).flags.contains(TypeFlags::HAS_ERROR);
+ let is_partially_unknown = ty.references_non_lt_error();
if is_partially_unknown {
num_pats_partially_unknown += 1;
}
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index 0dea285e97..44af8fbddf 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -9,6 +9,8 @@
//! The `cli` submodule implements some batch-processing analysis, primarily as
//! a debugging aid.
+extern crate ra_ap_rustc_type_ir as rustc_type_ir;
+
/// Any toolchain less than this version will likely not work with rust-analyzer built from this revision.
pub const MINIMUM_SUPPORTED_TOOLCHAIN_VERSION: semver::Version = semver::Version {
major: 1,