Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lib.rs')
-rw-r--r--crates/hir-ty/src/lib.rs398
1 files changed, 200 insertions, 198 deletions
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 76cc65277c..734483a823 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -39,7 +39,7 @@ mod utils;
pub mod autoderef;
pub mod consteval;
-pub mod consteval_chalk;
+mod consteval_chalk;
pub mod db;
pub mod diagnostics;
pub mod display;
@@ -62,7 +62,7 @@ mod variance;
use std::hash::Hash;
use chalk_ir::{
- NoSolution, VariableKinds,
+ VariableKinds,
fold::{Shift, TypeFoldable},
interner::HasInterner,
};
@@ -74,15 +74,16 @@ use la_arena::{Arena, Idx};
use mir::{MirEvalError, VTableMap};
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
use rustc_type_ir::{
- UpcastFrom,
- inherent::{SliceLike, Ty as _},
+ TypeSuperVisitable, TypeVisitableExt, UpcastFrom,
+ inherent::{IntoKind, SliceLike, Ty as _},
};
use syntax::ast::{ConstArg, make};
use traits::FnTrait;
use triomphe::Arc;
+#[cfg(not(debug_assertions))]
+use crate::next_solver::ErrorGuaranteed;
use crate::{
- consteval::unknown_const,
db::HirDatabase,
display::{DisplayTarget, HirDisplay},
generics::Generics,
@@ -104,11 +105,10 @@ pub use infer::{
could_coerce, could_unify, could_unify_deeply,
};
pub use interner::Interner;
-pub use lower::{
- ImplTraitLoweringMode, LifetimeElisionKind, ParamLoweringMode, TyDefId, TyLoweringContext,
- ValueTyDefId, diagnostics::*,
+pub use lower::{ImplTraitLoweringMode, ParamLoweringMode, TyDefId, ValueTyDefId, diagnostics::*};
+pub use lower_nextsolver::{
+ LifetimeElisionKind, TyLoweringContext, associated_type_shorthand_candidates,
};
-pub use lower_nextsolver::associated_type_shorthand_candidates;
pub use mapping::{
ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
@@ -124,20 +124,16 @@ pub use utils::{
};
pub use variance::Variance;
-pub use chalk_ir::{
- AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
- cast::Cast,
- visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
-};
+use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Safety, Scalar};
-pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
-pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
-pub type FnDefId = chalk_ir::FnDefId<Interner>;
-pub type ClosureId = chalk_ir::ClosureId<Interner>;
-pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
-pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
+pub(crate) type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
+pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
+pub(crate) type FnDefId = chalk_ir::FnDefId<Interner>;
+pub(crate) type ClosureId = chalk_ir::ClosureId<Interner>;
+pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
+pub(crate) type PlaceholderIndex = chalk_ir::PlaceholderIndex;
-pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
+pub(crate) type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
pub(crate) type VariableKind = chalk_ir::VariableKind<Interner>;
/// Represents generic parameters and an item bound by them. When the item has parent, the binders
@@ -148,49 +144,48 @@ pub(crate) type VariableKind = chalk_ir::VariableKind<Interner>;
/// parameters/arguments for an item MUST come before those for its parent. This is to facilitate
/// the integration with chalk-solve, which mildly puts constraints as such. See #13335 for its
/// motivation in detail.
-pub type Binders<T> = chalk_ir::Binders<T>;
+pub(crate) type Binders<T> = chalk_ir::Binders<T>;
/// Interned list of generic arguments for an item. When an item has parent, the `Substitution` for
/// it contains generic arguments for both its parent and itself. See chalk's documentation for
/// details.
///
/// See `Binders` for the constraint on the ordering.
-pub type Substitution = chalk_ir::Substitution<Interner>;
-pub type GenericArg = chalk_ir::GenericArg<Interner>;
-pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
+pub(crate) type Substitution = chalk_ir::Substitution<Interner>;
+pub(crate) type GenericArg = chalk_ir::GenericArg<Interner>;
+pub(crate) type GenericArgData = chalk_ir::GenericArgData<Interner>;
-pub type Ty = chalk_ir::Ty<Interner>;
+pub(crate) type Ty = chalk_ir::Ty<Interner>;
pub type TyKind = chalk_ir::TyKind<Interner>;
-pub type TypeFlags = chalk_ir::TypeFlags;
+pub(crate) type TypeFlags = chalk_ir::TypeFlags;
pub(crate) type DynTy = chalk_ir::DynTy<Interner>;
-pub type FnPointer = chalk_ir::FnPointer<Interner>;
+pub(crate) type FnPointer = chalk_ir::FnPointer<Interner>;
pub(crate) use chalk_ir::FnSubst; // a re-export so we don't lose the tuple constructor
pub type AliasTy = chalk_ir::AliasTy<Interner>;
-pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
+pub(crate) type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
pub(crate) type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
-pub(crate) type InferenceVar = chalk_ir::InferenceVar;
pub(crate) type Lifetime = chalk_ir::Lifetime<Interner>;
pub(crate) type LifetimeData = chalk_ir::LifetimeData<Interner>;
pub(crate) type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
-pub type ConstValue = chalk_ir::ConstValue<Interner>;
+pub(crate) type ConstValue = chalk_ir::ConstValue<Interner>;
-pub type Const = chalk_ir::Const<Interner>;
+pub(crate) type Const = chalk_ir::Const<Interner>;
pub(crate) type ConstData = chalk_ir::ConstData<Interner>;
pub(crate) type ConcreteConst = chalk_ir::ConcreteConst<Interner>;
-pub type TraitRef = chalk_ir::TraitRef<Interner>;
-pub type QuantifiedWhereClause = Binders<WhereClause>;
-pub type Canonical<T> = chalk_ir::Canonical<T>;
+pub(crate) type TraitRef = chalk_ir::TraitRef<Interner>;
+pub(crate) type QuantifiedWhereClause = Binders<WhereClause>;
+pub(crate) type Canonical<T> = chalk_ir::Canonical<T>;
pub(crate) type ChalkTraitId = chalk_ir::TraitId<Interner>;
pub(crate) type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;
pub(crate) type FnSig = chalk_ir::FnSig<Interner>;
-pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
+pub(crate) type InEnvironment<T> = chalk_ir::InEnvironment<T>;
pub type AliasEq = chalk_ir::AliasEq<Interner>;
pub type WhereClause = chalk_ir::WhereClause<Interner>;
@@ -717,130 +712,167 @@ pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<
/// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
/// ensures there are no unbound variables or inference variables anywhere in
/// the `t`.
-pub fn replace_errors_with_variables<T>(t: &T) -> Canonical<T>
+pub fn replace_errors_with_variables<'db, T>(
+ interner: DbInterner<'db>,
+ t: &T,
+) -> crate::next_solver::Canonical<'db, T>
where
- T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + Clone,
+ T: rustc_type_ir::TypeFoldable<DbInterner<'db>> + Clone,
{
- use chalk_ir::{
- Fallible,
- fold::{FallibleTypeFolder, TypeSuperFoldable},
- };
- struct ErrorReplacer {
- vars: usize,
+ use rustc_type_ir::{FallibleTypeFolder, TypeSuperFoldable};
+ struct ErrorReplacer<'db> {
+ interner: DbInterner<'db>,
+ vars: Vec<crate::next_solver::CanonicalVarKind<'db>>,
+ binder: rustc_type_ir::DebruijnIndex,
}
- impl FallibleTypeFolder<Interner> for ErrorReplacer {
- type Error = NoSolution;
-
- fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> {
- self
+ impl<'db> FallibleTypeFolder<DbInterner<'db>> for ErrorReplacer<'db> {
+ #[cfg(debug_assertions)]
+ type Error = ();
+ #[cfg(not(debug_assertions))]
+ type Error = std::convert::Infallible;
+
+ fn cx(&self) -> DbInterner<'db> {
+ self.interner
}
- fn interner(&self) -> Interner {
- Interner
- }
-
- fn try_fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
- if let TyKind::Error = ty.kind(Interner) {
- let index = self.vars;
- self.vars += 1;
- Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(Interner))
- } else {
- ty.try_super_fold_with(self.as_dyn(), outer_binder)
- }
- }
-
- fn try_fold_inference_ty(
+ fn try_fold_binder<T>(
&mut self,
- _var: InferenceVar,
- _kind: TyVariableKind,
- _outer_binder: DebruijnIndex,
- ) -> Fallible<Ty> {
- if cfg!(debug_assertions) {
- // we don't want to just panic here, because then the error message
- // won't contain the whole thing, which would not be very helpful
- Err(NoSolution)
- } else {
- Ok(TyKind::Error.intern(Interner))
- }
+ t: crate::next_solver::Binder<'db, T>,
+ ) -> Result<crate::next_solver::Binder<'db, T>, Self::Error>
+ where
+ T: rustc_type_ir::TypeFoldable<DbInterner<'db>>,
+ {
+ self.binder.shift_in(1);
+ let result = t.try_super_fold_with(self);
+ self.binder.shift_out(1);
+ result
}
- fn try_fold_free_var_ty(
+ fn try_fold_ty(
&mut self,
- _bound_var: BoundVar,
- _outer_binder: DebruijnIndex,
- ) -> Fallible<Ty> {
- if cfg!(debug_assertions) {
- // we don't want to just panic here, because then the error message
- // won't contain the whole thing, which would not be very helpful
- Err(NoSolution)
- } else {
- Ok(TyKind::Error.intern(Interner))
+ t: crate::next_solver::Ty<'db>,
+ ) -> Result<crate::next_solver::Ty<'db>, Self::Error> {
+ if !t.has_type_flags(
+ rustc_type_ir::TypeFlags::HAS_ERROR
+ | rustc_type_ir::TypeFlags::HAS_TY_INFER
+ | rustc_type_ir::TypeFlags::HAS_CT_INFER
+ | rustc_type_ir::TypeFlags::HAS_RE_INFER,
+ ) {
+ return Ok(t);
}
- }
- fn try_fold_inference_const(
- &mut self,
- ty: Ty,
- _var: InferenceVar,
- _outer_binder: DebruijnIndex,
- ) -> Fallible<Const> {
- if cfg!(debug_assertions) {
- Err(NoSolution)
- } else {
- let interner = DbInterner::conjure();
- Ok(unknown_const(ty.to_nextsolver(interner)).to_chalk(interner))
+ #[cfg(debug_assertions)]
+ let error = || Err(());
+ #[cfg(not(debug_assertions))]
+ let error = || Ok(crate::next_solver::Ty::new_error(self.interner, ErrorGuaranteed));
+
+ match t.kind() {
+ crate::next_solver::TyKind::Error(_) => {
+ let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
+ self.vars.push(crate::next_solver::CanonicalVarKind::Ty {
+ ui: rustc_type_ir::UniverseIndex::ZERO,
+ sub_root: var,
+ });
+ Ok(crate::next_solver::Ty::new_bound(
+ self.interner,
+ self.binder,
+ crate::next_solver::BoundTy {
+ var,
+ kind: crate::next_solver::BoundTyKind::Anon,
+ },
+ ))
+ }
+ crate::next_solver::TyKind::Infer(_) => error(),
+ crate::next_solver::TyKind::Bound(index, _) if index > self.binder => error(),
+ _ => t.try_super_fold_with(self),
}
}
- fn try_fold_free_var_const(
+ fn try_fold_const(
&mut self,
- ty: Ty,
- _bound_var: BoundVar,
- _outer_binder: DebruijnIndex,
- ) -> Fallible<Const> {
- if cfg!(debug_assertions) {
- Err(NoSolution)
- } else {
- let interner = DbInterner::conjure();
- Ok(unknown_const(ty.to_nextsolver(interner)).to_chalk(interner))
+ ct: crate::next_solver::Const<'db>,
+ ) -> Result<crate::next_solver::Const<'db>, Self::Error> {
+ if !ct.has_type_flags(
+ rustc_type_ir::TypeFlags::HAS_ERROR
+ | rustc_type_ir::TypeFlags::HAS_TY_INFER
+ | rustc_type_ir::TypeFlags::HAS_CT_INFER
+ | rustc_type_ir::TypeFlags::HAS_RE_INFER,
+ ) {
+ return Ok(ct);
}
- }
- fn try_fold_inference_lifetime(
- &mut self,
- _var: InferenceVar,
- _outer_binder: DebruijnIndex,
- ) -> Fallible<Lifetime> {
- if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) }
+ #[cfg(debug_assertions)]
+ let error = || Err(());
+ #[cfg(not(debug_assertions))]
+ let error = || Ok(crate::next_solver::Const::error(self.interner));
+
+ match ct.kind() {
+ crate::next_solver::ConstKind::Error(_) => {
+ let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
+ self.vars.push(crate::next_solver::CanonicalVarKind::Const(
+ rustc_type_ir::UniverseIndex::ZERO,
+ ));
+ Ok(crate::next_solver::Const::new_bound(
+ self.interner,
+ self.binder,
+ crate::next_solver::BoundConst { var },
+ ))
+ }
+ crate::next_solver::ConstKind::Infer(_) => error(),
+ crate::next_solver::ConstKind::Bound(index, _) if index > self.binder => error(),
+ _ => ct.try_super_fold_with(self),
+ }
}
- fn try_fold_free_var_lifetime(
+ fn try_fold_region(
&mut self,
- _bound_var: BoundVar,
- _outer_binder: DebruijnIndex,
- ) -> Fallible<Lifetime> {
- if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) }
+ region: crate::next_solver::Region<'db>,
+ ) -> Result<crate::next_solver::Region<'db>, Self::Error> {
+ #[cfg(debug_assertions)]
+ let error = || Err(());
+ #[cfg(not(debug_assertions))]
+ let error = || Ok(crate::next_solver::Region::error(self.interner));
+
+ match region.kind() {
+ crate::next_solver::RegionKind::ReError(_) => {
+ let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
+ self.vars.push(crate::next_solver::CanonicalVarKind::Region(
+ rustc_type_ir::UniverseIndex::ZERO,
+ ));
+ Ok(crate::next_solver::Region::new_bound(
+ self.interner,
+ self.binder,
+ crate::next_solver::BoundRegion {
+ var,
+ kind: crate::next_solver::BoundRegionKind::Anon,
+ },
+ ))
+ }
+ crate::next_solver::RegionKind::ReVar(_) => error(),
+ crate::next_solver::RegionKind::ReBound(index, _) if index > self.binder => error(),
+ _ => Ok(region),
+ }
}
}
- let mut error_replacer = ErrorReplacer { vars: 0 };
- let value = match t.clone().try_fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) {
+
+ let mut error_replacer =
+ ErrorReplacer { vars: Vec::new(), binder: rustc_type_ir::DebruijnIndex::ZERO, interner };
+ let value = match t.clone().try_fold_with(&mut error_replacer) {
Ok(t) => t,
Err(_) => panic!("Encountered unbound or inference vars in {t:?}"),
};
- let kinds = (0..error_replacer.vars).map(|_| {
- chalk_ir::CanonicalVarKind::new(
- chalk_ir::VariableKind::Ty(TyVariableKind::General),
- chalk_ir::UniverseIndex::ROOT,
- )
- });
- Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
+ crate::next_solver::Canonical {
+ value,
+ max_universe: rustc_type_ir::UniverseIndex::ZERO,
+ variables: crate::next_solver::CanonicalVars::new_from_iter(interner, error_replacer.vars),
+ }
}
pub fn callable_sig_from_fn_trait<'db>(
- self_ty: &Ty,
+ self_ty: crate::next_solver::Ty<'db>,
trait_env: Arc<TraitEnvironment<'db>>,
db: &'db dyn HirDatabase,
-) -> Option<(FnTrait, CallableSig)> {
+) -> Option<(FnTrait, crate::next_solver::PolyFnSig<'db>)> {
let krate = trait_env.krate;
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
let output_assoc_type = fn_once_trait
@@ -857,7 +889,7 @@ 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 args = [self_ty, args_ty];
let trait_ref = crate::next_solver::TraitRef::new(table.interner(), fn_once_trait.into(), args);
let projection = crate::next_solver::Ty::new_alias(
table.interner(),
@@ -880,23 +912,24 @@ pub fn callable_sig_from_fn_trait<'db>(
))
.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 params = args_ty
- .as_tuple()?
- .iter(Interner)
- .map(|it| it.assert_ty_ref(Interner))
- .cloned();
+ let ret_ty = table.resolve_completely(return_ty);
+ let args_ty = table.resolve_completely(args_ty);
+ let crate::next_solver::TyKind::Tuple(params) = args_ty.kind() else {
+ return None;
+ };
+ let inputs_and_output = crate::next_solver::Tys::new_from_iter(
+ table.interner(),
+ params.iter().chain(std::iter::once(ret_ty)),
+ );
return Some((
fn_x,
- CallableSig::from_params_and_return(
- params,
- ret_ty,
- false,
- Safety::Safe,
- FnAbi::RustCall,
- ),
+ crate::next_solver::Binder::dummy(crate::next_solver::FnSig {
+ inputs_and_output,
+ c_variadic: false,
+ safety: crate::next_solver::abi::Safety::Safe,
+ abi: FnAbi::RustCall,
+ }),
));
}
}
@@ -906,74 +939,43 @@ pub fn callable_sig_from_fn_trait<'db>(
}
}
-struct PlaceholderCollector<'db> {
- db: &'db dyn HirDatabase,
- placeholders: FxHashSet<TypeOrConstParamId>,
-}
-
-impl PlaceholderCollector<'_> {
- fn collect(&mut self, idx: PlaceholderIndex) {
- let id = from_placeholder_idx(self.db, idx).0;
- self.placeholders.insert(id);
- }
+struct ParamCollector {
+ params: FxHashSet<TypeOrConstParamId>,
}
-impl TypeVisitor<Interner> for PlaceholderCollector<'_> {
- type BreakTy = ();
-
- fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
+impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for ParamCollector {
+ type Result = ();
- fn visit_ty(
- &mut self,
- ty: &Ty,
- outer_binder: DebruijnIndex,
- ) -> std::ops::ControlFlow<Self::BreakTy> {
- let has_placeholder_bits = TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER;
- let chalk_ir::TyData { kind, flags } = ty.data(Interner);
-
- if let TyKind::Placeholder(idx) = kind {
- self.collect(*idx);
- } else if flags.intersects(has_placeholder_bits) {
- return ty.super_visit_with(self, outer_binder);
- } else {
- // Fast path: don't visit inner types (e.g. generic arguments) when `flags` indicate
- // that there are no placeholders.
+ fn visit_ty(&mut self, ty: crate::next_solver::Ty<'db>) -> Self::Result {
+ if let crate::next_solver::TyKind::Param(param) = ty.kind() {
+ self.params.insert(param.id.into());
}
- std::ops::ControlFlow::Continue(())
+ ty.super_visit_with(self);
}
- fn visit_const(
- &mut self,
- constant: &chalk_ir::Const<Interner>,
- _outer_binder: DebruijnIndex,
- ) -> std::ops::ControlFlow<Self::BreakTy> {
- if let chalk_ir::ConstValue::Placeholder(idx) = constant.data(Interner).value {
- self.collect(idx);
+ fn visit_const(&mut self, konst: crate::next_solver::Const<'db>) -> Self::Result {
+ if let crate::next_solver::ConstKind::Param(param) = konst.kind() {
+ self.params.insert(param.id.into());
}
- std::ops::ControlFlow::Continue(())
+
+ konst.super_visit_with(self);
}
}
-/// Returns unique placeholders for types and consts contained in `value`.
-pub fn collect_placeholders<T>(value: &T, db: &dyn HirDatabase) -> Vec<TypeOrConstParamId>
+/// Returns unique params for types and consts contained in `value`.
+pub fn collect_params<'db, T>(value: &T) -> Vec<TypeOrConstParamId>
where
- T: ?Sized + TypeVisitable<Interner>,
+ T: ?Sized + rustc_type_ir::TypeVisitable<DbInterner<'db>>,
{
- let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() };
- _ = value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
- collector.placeholders.into_iter().collect()
+ let mut collector = ParamCollector { params: FxHashSet::default() };
+ value.visit_with(&mut collector);
+ Vec::from_iter(collector.params)
}
-pub fn known_const_to_ast(
- konst: &Const,
- db: &dyn HirDatabase,
+pub fn known_const_to_ast<'db>(
+ konst: crate::next_solver::Const<'db>,
+ db: &'db dyn HirDatabase,
display_target: DisplayTarget,
) -> Option<ConstArg> {
Some(make::expr_const_value(konst.display(db, display_target).to_string().as_str()))