mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-16 01:38:13 +00:00
8419: Move hir_ty to Chalk IR r=flodiebold a=flodiebold Closes #8313. There's some further cleanups to do: - we're still using our `TypeWalk` in lots of places (not for mutating/folding though, just for walking) - we're still using our own canonicalization and unification and our `InferenceTable` - ~`ToChalk` still exists and gets called, it's just the identity in most cases now (I'll probably clean those up before merging this)~ 8423: Bump lsp-types and syn r=kjeremy a=kjeremy This lsp-types now supports a default InsertTextMode for completion and a per-completion item commit_characters Co-authored-by: Florian Diebold <flodiebold@gmail.com> Co-authored-by: kjeremy <kjeremy@gmail.com>
This commit is contained in:
commit
72ad5cbe16
19 changed files with 345 additions and 1551 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -852,9 +852,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lsp-types"
|
||||
version = "0.88.0"
|
||||
version = "0.89.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8e8e042772e4e10b3785822f63c82399d0dd233825de44d2596f7fa86e023e0"
|
||||
checksum = "07731ecd4ee0654728359a5b95e2a254c857876c04b85225496a35d60345daa7"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"serde",
|
||||
|
@ -1577,9 +1577,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.68"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
|
||||
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -1903,7 +1903,9 @@ impl Type {
|
|||
| TyKind::Dyn(_)
|
||||
| TyKind::Function(_)
|
||||
| TyKind::Alias(_)
|
||||
| TyKind::Foreign(_) => false,
|
||||
| TyKind::Foreign(_)
|
||||
| TyKind::Generator(..)
|
||||
| TyKind::GeneratorWitness(..) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::iter;
|
|||
|
||||
use chalk_ir::{
|
||||
cast::{Cast, CastTo, Caster},
|
||||
fold::Fold,
|
||||
interner::HasInterner,
|
||||
AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
|
||||
};
|
||||
|
@ -13,7 +14,7 @@ use smallvec::SmallVec;
|
|||
use crate::{
|
||||
db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
|
||||
CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution,
|
||||
TraitRef, Ty, TyDefId, TyExt, TyKind, TypeWalk, ValueTyDefId,
|
||||
TraitRef, Ty, TyDefId, TyExt, TyKind, ValueTyDefId,
|
||||
};
|
||||
|
||||
/// This is a builder for `Ty` or anything that needs a `Substitution`.
|
||||
|
@ -32,8 +33,7 @@ impl<D> TyBuilder<D> {
|
|||
|
||||
fn build_internal(self) -> (D, Substitution) {
|
||||
assert_eq!(self.vec.len(), self.param_count);
|
||||
// FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form
|
||||
let subst = Substitution::intern(self.vec);
|
||||
let subst = Substitution::from_iter(&Interner, self.vec);
|
||||
(self.data, subst)
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ impl TyBuilder<hir_def::AdtId> {
|
|||
self.vec.push(fallback().cast(&Interner));
|
||||
} else {
|
||||
// each default can depend on the previous parameters
|
||||
let subst_so_far = Substitution::intern(self.vec.clone());
|
||||
let subst_so_far = Substitution::from_iter(&Interner, self.vec.clone());
|
||||
self.vec
|
||||
.push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner));
|
||||
}
|
||||
|
@ -196,13 +196,13 @@ impl TyBuilder<TypeAliasId> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> {
|
||||
impl<T: HasInterner<Interner = Interner> + Fold<Interner>> TyBuilder<Binders<T>> {
|
||||
fn subst_binders(b: Binders<T>) -> Self {
|
||||
let param_count = b.binders.len(&Interner);
|
||||
TyBuilder::new(b, param_count)
|
||||
}
|
||||
|
||||
pub fn build(self) -> T {
|
||||
pub fn build(self) -> <T as Fold<Interner>>::Result {
|
||||
let (b, subst) = self.build_internal();
|
||||
b.substitute(&Interner, &subst)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
//! Implementations of the Chalk `Cast` trait for our types.
|
||||
|
||||
use chalk_ir::{
|
||||
cast::{Cast, CastTo},
|
||||
interner::HasInterner,
|
||||
};
|
||||
use chalk_ir::interner::HasInterner;
|
||||
|
||||
use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause};
|
||||
use crate::{CallableSig, ReturnTypeImplTraits};
|
||||
|
||||
macro_rules! has_interner {
|
||||
($t:ty) => {
|
||||
|
@ -15,59 +12,5 @@ macro_rules! has_interner {
|
|||
};
|
||||
}
|
||||
|
||||
has_interner!(WhereClause);
|
||||
has_interner!(DomainGoal);
|
||||
has_interner!(GenericArg);
|
||||
has_interner!(Ty);
|
||||
|
||||
impl CastTo<WhereClause> for TraitRef {
|
||||
fn cast_to(self, _interner: &Interner) -> WhereClause {
|
||||
WhereClause::Implemented(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl CastTo<WhereClause> for AliasEq {
|
||||
fn cast_to(self, _interner: &Interner) -> WhereClause {
|
||||
WhereClause::AliasEq(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl CastTo<DomainGoal> for WhereClause {
|
||||
fn cast_to(self, _interner: &Interner) -> DomainGoal {
|
||||
DomainGoal::Holds(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl CastTo<GenericArg> for Ty {
|
||||
fn cast_to(self, interner: &Interner) -> GenericArg {
|
||||
GenericArg::new(interner, GenericArgData::Ty(self))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! transitive_impl {
|
||||
($a:ty, $b:ty, $c:ty) => {
|
||||
impl CastTo<$c> for $a {
|
||||
fn cast_to(self, interner: &Interner) -> $c {
|
||||
self.cast::<$b>(interner).cast(interner)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// In Chalk, these can be done as blanket impls, but that doesn't work here
|
||||
// because of coherence
|
||||
|
||||
transitive_impl!(TraitRef, WhereClause, DomainGoal);
|
||||
transitive_impl!(AliasEq, WhereClause, DomainGoal);
|
||||
|
||||
macro_rules! reflexive_impl {
|
||||
($a:ty) => {
|
||||
impl CastTo<$a> for $a {
|
||||
fn cast_to(self, _interner: &Interner) -> $a {
|
||||
self
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
reflexive_impl!(GenericArg);
|
||||
has_interner!(CallableSig);
|
||||
has_interner!(ReturnTypeImplTraits);
|
||||
|
|
|
@ -287,6 +287,8 @@ impl HirDisplay for GenericArg {
|
|||
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
match self.interned() {
|
||||
crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
|
||||
crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
|
||||
crate::GenericArgData::Const(c) => c.hir_fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -664,6 +666,8 @@ impl HirDisplay for Ty {
|
|||
write!(f, "{{unknown}}")?;
|
||||
}
|
||||
TyKind::InferenceVar(..) => write!(f, "_")?,
|
||||
TyKind::Generator(..) => write!(f, "{{generator}}")?,
|
||||
TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -741,7 +745,7 @@ fn write_bounds_like_dyn_trait(
|
|||
if !first {
|
||||
write!(f, " + ")?;
|
||||
}
|
||||
// We assume that the self type is $0 (i.e. the
|
||||
// We assume that the self type is ^0.0 (i.e. the
|
||||
// existential) here, which is the only thing that's
|
||||
// possible in actual Rust, and hence don't print it
|
||||
write!(f, "{}", f.db.trait_data(trait_).name)?;
|
||||
|
@ -783,6 +787,10 @@ fn write_bounds_like_dyn_trait(
|
|||
}
|
||||
ty.hir_fmt(f)?;
|
||||
}
|
||||
|
||||
// FIXME implement these
|
||||
WhereClause::LifetimeOutlives(_) => {}
|
||||
WhereClause::TypeOutlives(_) => {}
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
@ -837,6 +845,10 @@ impl HirDisplay for WhereClause {
|
|||
ty.hir_fmt(f)?;
|
||||
}
|
||||
WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
|
||||
|
||||
// FIXME implement these
|
||||
WhereClause::TypeOutlives(..) => {}
|
||||
WhereClause::LifetimeOutlives(..) => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -881,9 +893,11 @@ impl HirDisplay for DomainGoal {
|
|||
DomainGoal::Holds(wc) => {
|
||||
write!(f, "Holds(")?;
|
||||
wc.hir_fmt(f)?;
|
||||
write!(f, ")")
|
||||
write!(f, ")")?;
|
||||
}
|
||||
_ => write!(f, "?")?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use std::mem;
|
|||
use std::ops::Index;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chalk_ir::{cast::Cast, Mutability};
|
||||
use chalk_ir::{cast::Cast, DebruijnIndex, Mutability};
|
||||
use hir_def::{
|
||||
body::Body,
|
||||
data::{ConstData, FunctionData, StaticData},
|
||||
|
@ -38,11 +38,11 @@ use syntax::SmolStr;
|
|||
|
||||
use super::{
|
||||
DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
|
||||
TypeWalk,
|
||||
};
|
||||
use crate::{
|
||||
db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
|
||||
to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, TyBuilder, TyExt, TyKind,
|
||||
db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic,
|
||||
lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner,
|
||||
TyBuilder, TyExt, TyKind,
|
||||
};
|
||||
|
||||
// This lint has a false positive here. See the link below for details.
|
||||
|
@ -323,7 +323,7 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
|
||||
fn insert_type_vars(&mut self, ty: Ty) -> Ty {
|
||||
ty.fold(&mut |ty| self.insert_type_vars_shallow(ty))
|
||||
fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST)
|
||||
}
|
||||
|
||||
fn resolve_obligations_as_possible(&mut self) {
|
||||
|
@ -434,12 +434,16 @@ impl<'a> InferenceContext<'a> {
|
|||
/// to do it as well.
|
||||
fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
|
||||
let ty = self.resolve_ty_as_possible(ty);
|
||||
ty.fold(&mut |ty| match ty.kind(&Interner) {
|
||||
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
|
||||
self.normalize_projection_ty(proj_ty.clone())
|
||||
}
|
||||
_ => ty,
|
||||
})
|
||||
fold_tys(
|
||||
ty,
|
||||
|ty, _| match ty.kind(&Interner) {
|
||||
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
|
||||
self.normalize_projection_ty(proj_ty.clone())
|
||||
}
|
||||
_ => ty,
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
}
|
||||
|
||||
fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
|
||||
|
|
|
@ -71,12 +71,14 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
|
||||
// Pointer weakening and function to pointer
|
||||
match (from_ty.interned_mut(), to_ty.kind(&Interner)) {
|
||||
match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
|
||||
// `*mut T` -> `*const T`
|
||||
(TyKind::Raw(_, inner), TyKind::Raw(m2 @ Mutability::Not, ..)) => {
|
||||
from_ty = TyKind::Raw(*m2, inner.clone()).intern(&Interner);
|
||||
}
|
||||
// `&mut T` -> `&T`
|
||||
(TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..))
|
||||
| (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
|
||||
*m1 = *m2;
|
||||
(TyKind::Ref(_, lt, inner), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
|
||||
from_ty = TyKind::Ref(*m2, lt.clone(), inner.clone()).intern(&Interner);
|
||||
}
|
||||
// `&T` -> `*const T`
|
||||
// `&mut T` -> `*mut T`/`*const T`
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::iter::{repeat, repeat_with};
|
||||
use std::{mem, sync::Arc};
|
||||
|
||||
use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
|
||||
use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
|
||||
use hir_def::{
|
||||
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
|
||||
path::{GenericArg, GenericArgs},
|
||||
|
@ -24,7 +24,6 @@ use crate::{
|
|||
utils::{generics, Generics},
|
||||
AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
|
||||
ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
|
||||
TypeWalk,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
|
|
@ -2,14 +2,17 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind};
|
||||
use chalk_ir::{
|
||||
cast::Cast, fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex,
|
||||
VariableKind,
|
||||
};
|
||||
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
||||
|
||||
use super::{DomainGoal, InferenceContext};
|
||||
use crate::{
|
||||
AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSubst,
|
||||
InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyExt, TyKind, TypeWalk,
|
||||
WhereClause,
|
||||
fold_tys, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
|
||||
DebruijnIndex, FnPointer, FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution,
|
||||
Ty, TyExt, TyKind, WhereClause,
|
||||
};
|
||||
|
||||
impl<'a> InferenceContext<'a> {
|
||||
|
@ -34,7 +37,10 @@ where
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct Canonicalized<T> {
|
||||
pub(super) struct Canonicalized<T>
|
||||
where
|
||||
T: HasInterner<Interner = Interner>,
|
||||
{
|
||||
pub(super) value: Canonical<T>,
|
||||
free_vars: Vec<(InferenceVar, TyVariableKind)>,
|
||||
}
|
||||
|
@ -48,9 +54,14 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
|
|||
})
|
||||
}
|
||||
|
||||
fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
|
||||
t.fold_binders(
|
||||
&mut |ty, binders| match ty.kind(&Interner) {
|
||||
fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
|
||||
&mut self,
|
||||
t: T,
|
||||
binders: DebruijnIndex,
|
||||
) -> T {
|
||||
fold_tys(
|
||||
t,
|
||||
|ty, binders| match ty.kind(&Interner) {
|
||||
&TyKind::InferenceVar(var, kind) => {
|
||||
let inner = from_inference_var(var);
|
||||
if self.var_stack.contains(&inner) {
|
||||
|
@ -76,7 +87,10 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
|
|||
)
|
||||
}
|
||||
|
||||
fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
|
||||
fn into_canonicalized<T: HasInterner<Interner = Interner>>(
|
||||
self,
|
||||
result: T,
|
||||
) -> Canonicalized<T> {
|
||||
let kinds = self
|
||||
.free_vars
|
||||
.iter()
|
||||
|
@ -103,28 +117,18 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
|
|||
DomainGoal::Holds(wc) => {
|
||||
DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Canonicalized<T> {
|
||||
impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
|
||||
pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty {
|
||||
ty.fold_binders(
|
||||
&mut |ty, binders| {
|
||||
if let TyKind::BoundVar(bound) = ty.kind(&Interner) {
|
||||
if bound.debruijn >= binders {
|
||||
let (v, k) = self.free_vars[bound.index];
|
||||
TyKind::InferenceVar(v, k).intern(&Interner)
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
crate::fold_free_vars(ty, |bound, _binders| {
|
||||
let (v, k) = self.free_vars[bound.index];
|
||||
TyKind::InferenceVar(v, k).intern(&Interner)
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn apply_solution(
|
||||
|
@ -136,15 +140,17 @@ impl<T> Canonicalized<T> {
|
|||
let new_vars = Substitution::from_iter(
|
||||
&Interner,
|
||||
solution.binders.iter(&Interner).map(|k| match k.kind {
|
||||
VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(),
|
||||
VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(),
|
||||
VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(),
|
||||
// HACK: Chalk can sometimes return new lifetime variables. We
|
||||
// want to just skip them, but to not mess up the indices of
|
||||
// other variables, we'll just create a new type variable in
|
||||
// their place instead. This should not matter (we never see the
|
||||
// actual *uses* of the lifetime variable).
|
||||
VariableKind::Lifetime => ctx.table.new_type_var(),
|
||||
VariableKind::Ty(TyVariableKind::General) => {
|
||||
ctx.table.new_type_var().cast(&Interner)
|
||||
}
|
||||
VariableKind::Ty(TyVariableKind::Integer) => {
|
||||
ctx.table.new_integer_var().cast(&Interner)
|
||||
}
|
||||
VariableKind::Ty(TyVariableKind::Float) => {
|
||||
ctx.table.new_float_var().cast(&Interner)
|
||||
}
|
||||
// Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere
|
||||
VariableKind::Lifetime => static_lifetime().cast(&Interner),
|
||||
_ => panic!("const variable in solution"),
|
||||
}),
|
||||
);
|
||||
|
@ -488,55 +494,63 @@ impl InferenceTable {
|
|||
/// be resolved as far as possible, i.e. contain no type variables with
|
||||
/// known type.
|
||||
fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
|
||||
ty.fold(&mut |ty| match ty.kind(&Interner) {
|
||||
&TyKind::InferenceVar(tv, kind) => {
|
||||
let inner = from_inference_var(tv);
|
||||
if tv_stack.contains(&inner) {
|
||||
cov_mark::hit!(type_var_cycles_resolve_as_possible);
|
||||
// recursive type
|
||||
return self.type_variable_table.fallback_value(tv, kind);
|
||||
fold_tys(
|
||||
ty,
|
||||
|ty, _| match ty.kind(&Interner) {
|
||||
&TyKind::InferenceVar(tv, kind) => {
|
||||
let inner = from_inference_var(tv);
|
||||
if tv_stack.contains(&inner) {
|
||||
cov_mark::hit!(type_var_cycles_resolve_as_possible);
|
||||
// recursive type
|
||||
return self.type_variable_table.fallback_value(tv, kind);
|
||||
}
|
||||
if let Some(known_ty) =
|
||||
self.var_unification_table.inlined_probe_value(inner).known()
|
||||
{
|
||||
// known_ty may contain other variables that are known by now
|
||||
tv_stack.push(inner);
|
||||
let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
|
||||
tv_stack.pop();
|
||||
result
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
}
|
||||
if let Some(known_ty) =
|
||||
self.var_unification_table.inlined_probe_value(inner).known()
|
||||
{
|
||||
// known_ty may contain other variables that are known by now
|
||||
tv_stack.push(inner);
|
||||
let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
|
||||
tv_stack.pop();
|
||||
result
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
}
|
||||
_ => ty,
|
||||
})
|
||||
_ => ty,
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
}
|
||||
|
||||
/// Resolves the type completely; type variables without known type are
|
||||
/// replaced by TyKind::Unknown.
|
||||
fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
|
||||
ty.fold(&mut |ty| match ty.kind(&Interner) {
|
||||
&TyKind::InferenceVar(tv, kind) => {
|
||||
let inner = from_inference_var(tv);
|
||||
if tv_stack.contains(&inner) {
|
||||
cov_mark::hit!(type_var_cycles_resolve_completely);
|
||||
// recursive type
|
||||
return self.type_variable_table.fallback_value(tv, kind);
|
||||
fold_tys(
|
||||
ty,
|
||||
|ty, _| match ty.kind(&Interner) {
|
||||
&TyKind::InferenceVar(tv, kind) => {
|
||||
let inner = from_inference_var(tv);
|
||||
if tv_stack.contains(&inner) {
|
||||
cov_mark::hit!(type_var_cycles_resolve_completely);
|
||||
// recursive type
|
||||
return self.type_variable_table.fallback_value(tv, kind);
|
||||
}
|
||||
if let Some(known_ty) =
|
||||
self.var_unification_table.inlined_probe_value(inner).known()
|
||||
{
|
||||
// known_ty may contain other variables that are known by now
|
||||
tv_stack.push(inner);
|
||||
let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
|
||||
tv_stack.pop();
|
||||
result
|
||||
} else {
|
||||
self.type_variable_table.fallback_value(tv, kind)
|
||||
}
|
||||
}
|
||||
if let Some(known_ty) =
|
||||
self.var_unification_table.inlined_probe_value(inner).known()
|
||||
{
|
||||
// known_ty may contain other variables that are known by now
|
||||
tv_stack.push(inner);
|
||||
let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
|
||||
tv_stack.pop();
|
||||
result
|
||||
} else {
|
||||
self.type_variable_table.fallback_value(tv, kind)
|
||||
}
|
||||
}
|
||||
_ => ty,
|
||||
})
|
||||
_ => ty,
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! The type system. We currently use this to infer types for completion, hover
|
||||
//! information and various assists.
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! eprintln {
|
||||
($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
|
||||
|
@ -17,7 +18,6 @@ mod chalk_cast;
|
|||
mod chalk_ext;
|
||||
mod builder;
|
||||
mod walk;
|
||||
mod types;
|
||||
|
||||
pub mod display;
|
||||
pub mod db;
|
||||
|
@ -31,7 +31,11 @@ mod test_db;
|
|||
use std::sync::Arc;
|
||||
|
||||
use base_db::salsa;
|
||||
use chalk_ir::UintTy;
|
||||
use chalk_ir::{
|
||||
fold::{Fold, Shift},
|
||||
interner::HasInterner,
|
||||
UintTy,
|
||||
};
|
||||
use hir_def::{
|
||||
expr::ExprId, type_ref::Rawness, ConstParamId, LifetimeParamId, TraitId, TypeAliasId,
|
||||
TypeParamId,
|
||||
|
@ -48,7 +52,6 @@ pub use lower::{
|
|||
TyDefId, TyLoweringContext, ValueTyDefId,
|
||||
};
|
||||
pub use traits::{chalk::Interner, TraitEnvironment};
|
||||
pub use types::*;
|
||||
pub use walk::TypeWalk;
|
||||
|
||||
pub use chalk_ir::{
|
||||
|
@ -65,6 +68,21 @@ pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
|
|||
pub type VariableKind = chalk_ir::VariableKind<Interner>;
|
||||
pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
|
||||
pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
|
||||
pub type Binders<T> = chalk_ir::Binders<T>;
|
||||
pub type Substitution = chalk_ir::Substitution<Interner>;
|
||||
pub type GenericArg = chalk_ir::GenericArg<Interner>;
|
||||
pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
|
||||
|
||||
pub type Ty = chalk_ir::Ty<Interner>;
|
||||
pub type TyKind = chalk_ir::TyKind<Interner>;
|
||||
pub type DynTy = chalk_ir::DynTy<Interner>;
|
||||
pub type FnPointer = chalk_ir::FnPointer<Interner>;
|
||||
// pub type FnSubst = chalk_ir::FnSubst<Interner>;
|
||||
pub use chalk_ir::FnSubst;
|
||||
pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
|
||||
pub type AliasTy = chalk_ir::AliasTy<Interner>;
|
||||
pub type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
|
||||
pub type InferenceVar = chalk_ir::InferenceVar;
|
||||
|
||||
pub type Lifetime = chalk_ir::Lifetime<Interner>;
|
||||
pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
|
||||
|
@ -79,9 +97,20 @@ pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
|
|||
|
||||
pub type FnSig = chalk_ir::FnSig<Interner>;
|
||||
|
||||
pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
|
||||
pub type DomainGoal = chalk_ir::DomainGoal<Interner>;
|
||||
pub type AliasEq = chalk_ir::AliasEq<Interner>;
|
||||
pub type Solution = chalk_solve::Solution<Interner>;
|
||||
pub type ConstrainedSubst = chalk_ir::ConstrainedSubst<Interner>;
|
||||
pub type Guidance = chalk_solve::Guidance<Interner>;
|
||||
pub type WhereClause = chalk_ir::WhereClause<Interner>;
|
||||
|
||||
// FIXME: get rid of this
|
||||
pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
|
||||
Substitution::intern(s.interned()[..std::cmp::min(s.len(&Interner), n)].into())
|
||||
Substitution::from_iter(
|
||||
&Interner,
|
||||
s.interned()[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Return an index of a parameter in the generic type parameter list by it's id.
|
||||
|
@ -91,12 +120,15 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
|
|||
|
||||
pub fn wrap_empty_binders<T>(value: T) -> Binders<T>
|
||||
where
|
||||
T: TypeWalk,
|
||||
T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>,
|
||||
{
|
||||
Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE))
|
||||
Binders::empty(&Interner, value.shifted_in_from(&Interner, DebruijnIndex::ONE))
|
||||
}
|
||||
|
||||
pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> {
|
||||
pub fn make_only_type_binders<T: HasInterner<Interner = Interner>>(
|
||||
num_vars: usize,
|
||||
value: T,
|
||||
) -> Binders<T> {
|
||||
Binders::new(
|
||||
VariableKinds::from_iter(
|
||||
&Interner,
|
||||
|
@ -108,7 +140,7 @@ pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> {
|
|||
}
|
||||
|
||||
// FIXME: get rid of this
|
||||
pub fn make_canonical<T>(
|
||||
pub fn make_canonical<T: HasInterner<Interner = Interner>>(
|
||||
value: T,
|
||||
kinds: impl IntoIterator<Item = TyVariableKind>,
|
||||
) -> Canonical<T> {
|
||||
|
@ -121,6 +153,14 @@ pub fn make_canonical<T>(
|
|||
Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
|
||||
}
|
||||
|
||||
pub type TraitRef = chalk_ir::TraitRef<Interner>;
|
||||
|
||||
pub type QuantifiedWhereClause = Binders<WhereClause>;
|
||||
|
||||
pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;
|
||||
|
||||
pub type Canonical<T> = chalk_ir::Canonical<T>;
|
||||
|
||||
/// A function signature as seen by type inference: Several parameter types and
|
||||
/// one return type.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
|
@ -144,7 +184,7 @@ impl CallableSig {
|
|||
params_and_return: fn_ptr
|
||||
.substitution
|
||||
.clone()
|
||||
.shifted_out_to(DebruijnIndex::ONE)
|
||||
.shifted_out_to(&Interner, DebruijnIndex::ONE)
|
||||
.expect("unexpected lifetime vars in fn ptr")
|
||||
.0
|
||||
.interned()
|
||||
|
@ -164,7 +204,22 @@ impl CallableSig {
|
|||
}
|
||||
}
|
||||
|
||||
impl Ty {}
|
||||
impl Fold<Interner> for CallableSig {
|
||||
type Result = CallableSig;
|
||||
|
||||
fn fold_with<'i>(
|
||||
self,
|
||||
folder: &mut dyn chalk_ir::fold::Folder<'i, Interner>,
|
||||
outer_binder: DebruijnIndex,
|
||||
) -> chalk_ir::Fallible<Self::Result>
|
||||
where
|
||||
Interner: 'i,
|
||||
{
|
||||
let vec = self.params_and_return.to_vec();
|
||||
let folded = vec.fold_with(folder, outer_binder)?;
|
||||
Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum ImplTraitId {
|
||||
|
@ -244,3 +299,56 @@ pub fn dummy_usize_const() -> Const {
|
|||
}
|
||||
.intern(&Interner)
|
||||
}
|
||||
|
||||
pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + Fold<Interner>>(
|
||||
t: T,
|
||||
f: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
|
||||
) -> T::Result {
|
||||
use chalk_ir::{fold::Folder, Fallible};
|
||||
struct FreeVarFolder<F>(F);
|
||||
impl<'i, F: FnMut(BoundVar, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for FreeVarFolder<F> {
|
||||
fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
|
||||
self
|
||||
}
|
||||
|
||||
fn interner(&self) -> &'i Interner {
|
||||
&Interner
|
||||
}
|
||||
|
||||
fn fold_free_var_ty(
|
||||
&mut self,
|
||||
bound_var: BoundVar,
|
||||
outer_binder: DebruijnIndex,
|
||||
) -> Fallible<Ty> {
|
||||
Ok(self.0(bound_var, outer_binder))
|
||||
}
|
||||
}
|
||||
t.fold_with(&mut FreeVarFolder(f), DebruijnIndex::INNERMOST).expect("fold failed unexpectedly")
|
||||
}
|
||||
|
||||
pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>(
|
||||
t: T,
|
||||
f: impl FnMut(Ty, DebruijnIndex) -> Ty,
|
||||
binders: DebruijnIndex,
|
||||
) -> T::Result {
|
||||
use chalk_ir::{
|
||||
fold::{Folder, SuperFold},
|
||||
Fallible,
|
||||
};
|
||||
struct TyFolder<F>(F);
|
||||
impl<'i, F: FnMut(Ty, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for TyFolder<F> {
|
||||
fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
|
||||
self
|
||||
}
|
||||
|
||||
fn interner(&self) -> &'i Interner {
|
||||
&Interner
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
|
||||
let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
|
||||
Ok(self.0(ty, outer_binder))
|
||||
}
|
||||
}
|
||||
t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
use std::{iter, sync::Arc};
|
||||
|
||||
use base_db::CrateId;
|
||||
use chalk_ir::{cast::Cast, Mutability, Safety};
|
||||
use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
|
||||
use hir_def::{
|
||||
adt::StructKind,
|
||||
builtin_type::BuiltinType,
|
||||
|
@ -35,7 +35,7 @@ use crate::{
|
|||
AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
|
||||
FnSubst, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
|
||||
QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution,
|
||||
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, TypeWalk, WhereClause,
|
||||
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -488,7 +488,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||
};
|
||||
// We need to shift in the bound vars, since
|
||||
// associated_type_shorthand_candidates does not do that
|
||||
let substs = substs.shifted_in_from(self.in_binders);
|
||||
let substs = substs.shifted_in_from(&Interner, self.in_binders);
|
||||
// FIXME handle type parameters on the segment
|
||||
return Some(
|
||||
TyKind::Alias(AliasTy::Projection(ProjectionTy {
|
||||
|
@ -847,7 +847,7 @@ pub fn associated_type_shorthand_candidates<R>(
|
|||
// FIXME: how to correctly handle higher-ranked bounds here?
|
||||
WhereClause::Implemented(tr) => search(
|
||||
tr.clone()
|
||||
.shifted_out_to(DebruijnIndex::ONE)
|
||||
.shifted_out_to(&Interner, DebruijnIndex::ONE)
|
||||
.expect("FIXME unexpected higher-ranked trait bound"),
|
||||
),
|
||||
_ => None,
|
||||
|
@ -950,8 +950,7 @@ pub(crate) fn trait_environment_query(
|
|||
traits_in_scope
|
||||
.push((tr.self_type_parameter(&Interner).clone(), tr.hir_trait_id()));
|
||||
}
|
||||
let program_clause: chalk_ir::ProgramClause<Interner> =
|
||||
pred.clone().to_chalk(db).cast(&Interner);
|
||||
let program_clause: chalk_ir::ProgramClause<Interner> = pred.clone().cast(&Interner);
|
||||
clauses.push(program_clause.into_from_env_clause(&Interner));
|
||||
}
|
||||
}
|
||||
|
@ -974,7 +973,7 @@ pub(crate) fn trait_environment_query(
|
|||
let substs = TyBuilder::type_params_subst(db, trait_id);
|
||||
let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
|
||||
let pred = WhereClause::Implemented(trait_ref);
|
||||
let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner);
|
||||
let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(&Interner);
|
||||
clauses.push(program_clause.into_from_env_clause(&Interner));
|
||||
}
|
||||
|
||||
|
@ -1016,22 +1015,16 @@ pub(crate) fn generic_defaults_query(
|
|||
p.default.as_ref().map_or(TyKind::Error.intern(&Interner), |t| ctx.lower_ty(t));
|
||||
|
||||
// Each default can only refer to previous parameters.
|
||||
ty = ty.fold_binders(
|
||||
&mut |ty, binders| match ty.kind(&Interner) {
|
||||
TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
|
||||
if *index >= idx {
|
||||
// type variable default referring to parameter coming
|
||||
// after it. This is forbidden (FIXME: report
|
||||
// diagnostic)
|
||||
TyKind::Error.intern(&Interner)
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
}
|
||||
_ => ty,
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
);
|
||||
ty = crate::fold_free_vars(ty, |bound, binders| {
|
||||
if bound.index >= idx && bound.debruijn == DebruijnIndex::INNERMOST {
|
||||
// type variable default referring to parameter coming
|
||||
// after it. This is forbidden (FIXME: report
|
||||
// diagnostic)
|
||||
TyKind::Error.intern(&Interner)
|
||||
} else {
|
||||
bound.shifted_in_from(binders).to_ty(&Interner)
|
||||
}
|
||||
});
|
||||
|
||||
crate::make_only_type_binders(idx, ty)
|
||||
})
|
||||
|
@ -1307,6 +1300,6 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
|
|||
}
|
||||
}
|
||||
|
||||
fn make_binders<T>(generics: &Generics, value: T) -> Binders<T> {
|
||||
fn make_binders<T: HasInterner<Interner = Interner>>(generics: &Generics, value: T) -> Binders<T> {
|
||||
crate::make_only_type_binders(generics.len(), value)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::{
|
|||
utils::all_super_traits,
|
||||
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId,
|
||||
InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder,
|
||||
TyExt, TyKind, TypeWalk,
|
||||
TyExt, TyKind,
|
||||
};
|
||||
|
||||
/// This is used as a key for indexing impls.
|
||||
|
@ -757,20 +757,13 @@ pub(crate) fn inherent_impl_substs(
|
|||
/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
|
||||
/// num_vars_to_keep) by `TyKind::Unknown`.
|
||||
fn fallback_bound_vars(s: Substitution, num_vars_to_keep: usize) -> Substitution {
|
||||
s.fold_binders(
|
||||
&mut |ty, binders| {
|
||||
if let TyKind::BoundVar(bound) = ty.kind(&Interner) {
|
||||
if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
|
||||
TyKind::Error.intern(&Interner)
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
crate::fold_free_vars(s, |bound, binders| {
|
||||
if bound.index >= num_vars_to_keep && bound.debruijn == DebruijnIndex::INNERMOST {
|
||||
TyKind::Error.intern(&Interner)
|
||||
} else {
|
||||
bound.shifted_in_from(binders).to_ty(&Interner)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn transform_receiver_ty(
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
Solution, TraitRefExt, Ty, TyKind, WhereClause,
|
||||
};
|
||||
|
||||
use self::chalk::{from_chalk, Interner, ToChalk};
|
||||
use self::chalk::Interner;
|
||||
|
||||
pub(crate) mod chalk;
|
||||
|
||||
|
@ -81,6 +81,7 @@ pub(crate) fn trait_solve_query(
|
|||
db.trait_data(it.hir_trait_id()).name.to_string()
|
||||
}
|
||||
DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
|
||||
_ => "??".to_string(),
|
||||
});
|
||||
log::info!("trait_solve_query({})", goal.value.goal.display(db));
|
||||
|
||||
|
@ -95,13 +96,12 @@ pub(crate) fn trait_solve_query(
|
|||
}
|
||||
}
|
||||
|
||||
let canonical = goal.to_chalk(db).cast(&Interner);
|
||||
let canonical = goal.cast(&Interner);
|
||||
|
||||
// We currently don't deal with universes (I think / hope they're not yet
|
||||
// relevant for our use cases?)
|
||||
let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
|
||||
let solution = solve(db, krate, &u_canonical);
|
||||
solution.map(|solution| solution_from_chalk(db, solution))
|
||||
solve(db, krate, &u_canonical)
|
||||
}
|
||||
|
||||
fn solve(
|
||||
|
@ -169,26 +169,6 @@ fn is_chalk_print() -> bool {
|
|||
std::env::var("CHALK_PRINT").is_ok()
|
||||
}
|
||||
|
||||
fn solution_from_chalk(
|
||||
db: &dyn HirDatabase,
|
||||
solution: chalk_solve::Solution<Interner>,
|
||||
) -> Solution {
|
||||
match solution {
|
||||
chalk_solve::Solution::Unique(constr_subst) => {
|
||||
Solution::Unique(from_chalk(db, constr_subst))
|
||||
}
|
||||
chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => {
|
||||
Solution::Ambig(Guidance::Definite(from_chalk(db, subst)))
|
||||
}
|
||||
chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => {
|
||||
Solution::Ambig(Guidance::Suggested(from_chalk(db, subst)))
|
||||
}
|
||||
chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => {
|
||||
Solution::Ambig(Guidance::Unknown)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum FnTrait {
|
||||
FnOnce,
|
||||
|
|
|
@ -17,16 +17,14 @@ use super::ChalkContext;
|
|||
use crate::{
|
||||
db::HirDatabase,
|
||||
display::HirDisplay,
|
||||
from_assoc_type_id,
|
||||
from_assoc_type_id, make_only_type_binders,
|
||||
method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
||||
to_assoc_type_id, to_chalk_trait_id,
|
||||
utils::generics,
|
||||
AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution,
|
||||
TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause,
|
||||
};
|
||||
use mapping::{
|
||||
convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
|
||||
};
|
||||
use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, TypeAliasAsValue};
|
||||
|
||||
pub use self::interner::Interner;
|
||||
pub(crate) use self::interner::*;
|
||||
|
@ -86,7 +84,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
debug!("impls_for_trait {:?}", trait_id);
|
||||
let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
|
||||
|
||||
let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
|
||||
let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone();
|
||||
|
||||
fn binder_kind(
|
||||
ty: &Ty,
|
||||
|
@ -187,16 +185,11 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
|
||||
let data = &datas.impl_traits[idx as usize];
|
||||
let bound = OpaqueTyDatumBound {
|
||||
bounds: make_binders(
|
||||
data.bounds
|
||||
.skip_binders()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|b| b.to_chalk(self.db))
|
||||
.collect(),
|
||||
bounds: make_only_type_binders(
|
||||
1,
|
||||
data.bounds.skip_binders().iter().cloned().collect(),
|
||||
),
|
||||
where_clauses: make_binders(vec![], 0),
|
||||
where_clauses: make_only_type_binders(0, vec![]),
|
||||
};
|
||||
chalk_ir::Binders::new(binders, bound)
|
||||
}
|
||||
|
@ -244,25 +237,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
.intern(&Interner),
|
||||
});
|
||||
let bound = OpaqueTyDatumBound {
|
||||
bounds: make_binders(
|
||||
vec![
|
||||
crate::wrap_empty_binders(impl_bound).to_chalk(self.db),
|
||||
crate::wrap_empty_binders(proj_bound).to_chalk(self.db),
|
||||
],
|
||||
bounds: make_only_type_binders(
|
||||
1,
|
||||
vec![
|
||||
crate::wrap_empty_binders(impl_bound),
|
||||
crate::wrap_empty_binders(proj_bound),
|
||||
],
|
||||
),
|
||||
where_clauses: make_binders(vec![], 0),
|
||||
where_clauses: make_only_type_binders(0, vec![]),
|
||||
};
|
||||
// The opaque type has 1 parameter.
|
||||
make_binders(bound, 1)
|
||||
make_only_type_binders(1, bound)
|
||||
} else {
|
||||
// If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback.
|
||||
let bound = OpaqueTyDatumBound {
|
||||
bounds: make_binders(vec![], 0),
|
||||
where_clauses: make_binders(vec![], 0),
|
||||
bounds: make_only_type_binders(0, vec![]),
|
||||
where_clauses: make_only_type_binders(0, vec![]),
|
||||
};
|
||||
// The opaque type has 1 parameter.
|
||||
make_binders(bound, 1)
|
||||
make_only_type_binders(1, bound)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -272,7 +265,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
|
||||
fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
|
||||
// FIXME: actually provide the hidden type; it is relevant for auto traits
|
||||
TyKind::Error.intern(&Interner).to_chalk(self.db)
|
||||
TyKind::Error.intern(&Interner)
|
||||
}
|
||||
|
||||
fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
|
||||
|
@ -293,29 +286,28 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
_closure_id: chalk_ir::ClosureId<Interner>,
|
||||
substs: &chalk_ir::Substitution<Interner>,
|
||||
) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
|
||||
let sig_ty: Ty =
|
||||
from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
|
||||
let sig_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone();
|
||||
let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr");
|
||||
let io = rust_ir::FnDefInputsAndOutputDatum {
|
||||
argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(),
|
||||
return_type: sig.ret().clone().to_chalk(self.db),
|
||||
argument_types: sig.params().iter().cloned().collect(),
|
||||
return_type: sig.ret().clone(),
|
||||
};
|
||||
make_binders(io.shifted_in(&Interner), 0)
|
||||
make_only_type_binders(0, io.shifted_in(&Interner))
|
||||
}
|
||||
fn closure_upvars(
|
||||
&self,
|
||||
_closure_id: chalk_ir::ClosureId<Interner>,
|
||||
_substs: &chalk_ir::Substitution<Interner>,
|
||||
) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
|
||||
let ty = TyBuilder::unit().to_chalk(self.db);
|
||||
make_binders(ty, 0)
|
||||
let ty = TyBuilder::unit();
|
||||
make_only_type_binders(0, ty)
|
||||
}
|
||||
fn closure_fn_substitution(
|
||||
&self,
|
||||
_closure_id: chalk_ir::ClosureId<Interner>,
|
||||
_substs: &chalk_ir::Substitution<Interner>,
|
||||
) -> chalk_ir::Substitution<Interner> {
|
||||
Substitution::empty(&Interner).to_chalk(self.db)
|
||||
Substitution::empty(&Interner)
|
||||
}
|
||||
|
||||
fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String {
|
||||
|
@ -410,10 +402,10 @@ pub(crate) fn associated_ty_data_query(
|
|||
let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
|
||||
let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses };
|
||||
let datum = AssociatedTyDatum {
|
||||
trait_id: trait_.to_chalk(db),
|
||||
trait_id: to_chalk_trait_id(trait_),
|
||||
id,
|
||||
name: type_alias,
|
||||
binders: make_binders(bound_data, generic_params.len()),
|
||||
binders: make_only_type_binders(generic_params.len(), bound_data),
|
||||
};
|
||||
Arc::new(datum)
|
||||
}
|
||||
|
@ -446,7 +438,7 @@ pub(crate) fn trait_datum_query(
|
|||
lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name));
|
||||
let trait_datum = TraitDatum {
|
||||
id: trait_id,
|
||||
binders: make_binders(trait_datum_bound, bound_vars.len(&Interner)),
|
||||
binders: make_only_type_binders(bound_vars.len(&Interner), trait_datum_bound),
|
||||
flags,
|
||||
associated_ty_ids,
|
||||
well_known,
|
||||
|
@ -515,7 +507,7 @@ pub(crate) fn struct_datum_query(
|
|||
// FIXME set ADT kind
|
||||
kind: rust_ir::AdtKind::Struct,
|
||||
id: struct_id,
|
||||
binders: make_binders(struct_datum_bound, num_params),
|
||||
binders: make_only_type_binders(num_params, struct_datum_bound),
|
||||
flags,
|
||||
};
|
||||
Arc::new(struct_datum)
|
||||
|
@ -563,7 +555,6 @@ fn impl_def_datum(
|
|||
trait_ref.display(db),
|
||||
where_clauses
|
||||
);
|
||||
let trait_ref = trait_ref.to_chalk(db);
|
||||
|
||||
let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
|
||||
|
||||
|
@ -585,7 +576,7 @@ fn impl_def_datum(
|
|||
.collect();
|
||||
debug!("impl_datum: {:?}", impl_datum_bound);
|
||||
let impl_datum = ImplDatum {
|
||||
binders: make_binders(impl_datum_bound, bound_vars.len(&Interner)),
|
||||
binders: make_only_type_binders(bound_vars.len(&Interner), impl_datum_bound),
|
||||
impl_type,
|
||||
polarity,
|
||||
associated_ty_value_ids,
|
||||
|
@ -624,7 +615,7 @@ fn type_alias_associated_ty_value(
|
|||
.associated_type_by_name(&type_alias_data.name)
|
||||
.expect("assoc ty value should not exist"); // validated when building the impl data as well
|
||||
let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
|
||||
let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
|
||||
let value_bound = rust_ir::AssociatedTyValueBound { ty };
|
||||
let value = rust_ir::AssociatedTyValue {
|
||||
impl_id: impl_id.to_chalk(db),
|
||||
associated_ty_id: to_assoc_type_id(assoc_ty),
|
||||
|
@ -645,13 +636,13 @@ pub(crate) fn fn_def_datum_query(
|
|||
let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
|
||||
let bound = rust_ir::FnDefDatumBound {
|
||||
// Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
|
||||
inputs_and_output: make_binders(
|
||||
inputs_and_output: make_only_type_binders(
|
||||
0,
|
||||
rust_ir::FnDefInputsAndOutputDatum {
|
||||
argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(),
|
||||
return_type: sig.ret().clone().to_chalk(db),
|
||||
argument_types: sig.params().iter().cloned().collect(),
|
||||
return_type: sig.ret().clone(),
|
||||
}
|
||||
.shifted_in(&Interner),
|
||||
0,
|
||||
),
|
||||
where_clauses,
|
||||
};
|
||||
|
|
|
@ -3,233 +3,20 @@
|
|||
//! Chalk (in both directions); plus some helper functions for more specialized
|
||||
//! conversions.
|
||||
|
||||
use chalk_ir::{cast::Cast, interner::HasInterner};
|
||||
use chalk_ir::cast::Cast;
|
||||
use chalk_solve::rust_ir;
|
||||
|
||||
use base_db::salsa::InternKey;
|
||||
use hir_def::{GenericDefId, TypeAliasId};
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, static_lifetime, AliasTy, CallableDefId, Canonical, ConstrainedSubst,
|
||||
DomainGoal, FnPointer, GenericArg, InEnvironment, OpaqueTy, ProjectionTy, ProjectionTyExt,
|
||||
QuantifiedWhereClause, Substitution, TraitRef, Ty, TypeWalk, WhereClause,
|
||||
db::HirDatabase, AliasTy, CallableDefId, ProjectionTyExt, QuantifiedWhereClause, Substitution,
|
||||
Ty, WhereClause,
|
||||
};
|
||||
|
||||
use super::interner::*;
|
||||
use super::*;
|
||||
|
||||
impl ToChalk for Ty {
|
||||
type Chalk = chalk_ir::Ty<Interner>;
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
|
||||
match self.into_inner() {
|
||||
TyKind::Ref(m, lt, ty) => {
|
||||
chalk_ir::TyKind::Ref(m, lt, ty.to_chalk(db)).intern(&Interner)
|
||||
}
|
||||
TyKind::Array(ty, size) => {
|
||||
chalk_ir::TyKind::Array(ty.to_chalk(db), size).intern(&Interner)
|
||||
}
|
||||
TyKind::Function(FnPointer { sig, substitution: substs, num_binders }) => {
|
||||
let substitution = chalk_ir::FnSubst(substs.0.to_chalk(db));
|
||||
chalk_ir::TyKind::Function(chalk_ir::FnPointer { num_binders, sig, substitution })
|
||||
.intern(&Interner)
|
||||
}
|
||||
TyKind::AssociatedType(assoc_type_id, substs) => {
|
||||
let substitution = substs.to_chalk(db);
|
||||
chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
|
||||
}
|
||||
|
||||
TyKind::OpaqueType(id, substs) => {
|
||||
let substitution = substs.to_chalk(db);
|
||||
chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner)
|
||||
}
|
||||
|
||||
TyKind::Foreign(id) => chalk_ir::TyKind::Foreign(id).intern(&Interner),
|
||||
|
||||
TyKind::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
|
||||
|
||||
TyKind::Tuple(cardinality, substs) => {
|
||||
let substitution = substs.to_chalk(db);
|
||||
chalk_ir::TyKind::Tuple(cardinality, substitution).intern(&Interner)
|
||||
}
|
||||
TyKind::Raw(mutability, ty) => {
|
||||
let ty = ty.to_chalk(db);
|
||||
chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
|
||||
}
|
||||
TyKind::Slice(ty) => chalk_ir::TyKind::Slice(ty.to_chalk(db)).intern(&Interner),
|
||||
TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
|
||||
TyKind::FnDef(id, substs) => {
|
||||
let substitution = substs.to_chalk(db);
|
||||
chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner)
|
||||
}
|
||||
TyKind::Never => chalk_ir::TyKind::Never.intern(&Interner),
|
||||
|
||||
TyKind::Closure(closure_id, substs) => {
|
||||
let substitution = substs.to_chalk(db);
|
||||
chalk_ir::TyKind::Closure(closure_id, substitution).intern(&Interner)
|
||||
}
|
||||
|
||||
TyKind::Adt(adt_id, substs) => {
|
||||
let substitution = substs.to_chalk(db);
|
||||
chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner)
|
||||
}
|
||||
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
|
||||
chalk_ir::AliasTy::Projection(proj_ty.to_chalk(db))
|
||||
.cast(&Interner)
|
||||
.intern(&Interner)
|
||||
}
|
||||
TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
|
||||
chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)).cast(&Interner).intern(&Interner)
|
||||
}
|
||||
TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner),
|
||||
TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
|
||||
TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
|
||||
TyKind::Dyn(dyn_ty) => {
|
||||
let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders();
|
||||
let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
|
||||
&Interner,
|
||||
bounds.interned().iter().cloned().map(|p| p.to_chalk(db)),
|
||||
);
|
||||
let bounded_ty = chalk_ir::DynTy {
|
||||
bounds: chalk_ir::Binders::new(binders, where_clauses),
|
||||
lifetime: dyn_ty.lifetime,
|
||||
};
|
||||
chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
|
||||
}
|
||||
TyKind::Error => chalk_ir::TyKind::Error.intern(&Interner),
|
||||
}
|
||||
}
|
||||
fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
|
||||
match chalk.data(&Interner).kind.clone() {
|
||||
chalk_ir::TyKind::Error => TyKind::Error,
|
||||
chalk_ir::TyKind::Array(ty, size) => TyKind::Array(from_chalk(db, ty), size),
|
||||
chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
|
||||
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
|
||||
TyKind::Alias(AliasTy::Projection(from_chalk(db, proj)))
|
||||
}
|
||||
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
|
||||
TyKind::Alias(AliasTy::Opaque(from_chalk(db, opaque_ty)))
|
||||
}
|
||||
chalk_ir::TyKind::Function(chalk_ir::FnPointer {
|
||||
num_binders,
|
||||
sig,
|
||||
substitution,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(num_binders, 0);
|
||||
let substs = crate::FnSubst(from_chalk(db, substitution.0));
|
||||
TyKind::Function(FnPointer { num_binders, sig, substitution: substs })
|
||||
}
|
||||
chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx),
|
||||
chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Error,
|
||||
chalk_ir::TyKind::Dyn(dyn_ty) => {
|
||||
assert_eq!(dyn_ty.bounds.binders.len(&Interner), 1);
|
||||
let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders();
|
||||
let where_clauses = crate::QuantifiedWhereClauses::from_iter(
|
||||
&Interner,
|
||||
bounds.interned().iter().cloned().map(|p| from_chalk(db, p)),
|
||||
);
|
||||
TyKind::Dyn(crate::DynTy {
|
||||
bounds: crate::Binders::new(binders, where_clauses),
|
||||
// HACK: we sometimes get lifetime variables back in solutions
|
||||
// from Chalk, and don't have the infrastructure to substitute
|
||||
// them yet. So for now we just turn them into 'static right
|
||||
// when we get them
|
||||
lifetime: static_lifetime(),
|
||||
})
|
||||
}
|
||||
|
||||
chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)),
|
||||
chalk_ir::TyKind::AssociatedType(type_id, subst) => {
|
||||
TyKind::AssociatedType(type_id, from_chalk(db, subst))
|
||||
}
|
||||
|
||||
chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => {
|
||||
TyKind::OpaqueType(opaque_type_id, from_chalk(db, subst))
|
||||
}
|
||||
|
||||
chalk_ir::TyKind::Scalar(scalar) => TyKind::Scalar(scalar),
|
||||
chalk_ir::TyKind::Tuple(cardinality, subst) => {
|
||||
TyKind::Tuple(cardinality, from_chalk(db, subst))
|
||||
}
|
||||
chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
|
||||
chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
|
||||
chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
|
||||
// HACK: we sometimes get lifetime variables back in solutions
|
||||
// from Chalk, and don't have the infrastructure to substitute
|
||||
// them yet. So for now we just turn them into 'static right
|
||||
// when we get them
|
||||
TyKind::Ref(mutability, static_lifetime(), from_chalk(db, ty))
|
||||
}
|
||||
chalk_ir::TyKind::Str => TyKind::Str,
|
||||
chalk_ir::TyKind::Never => TyKind::Never,
|
||||
|
||||
chalk_ir::TyKind::FnDef(fn_def_id, subst) => {
|
||||
TyKind::FnDef(fn_def_id, from_chalk(db, subst))
|
||||
}
|
||||
|
||||
chalk_ir::TyKind::Closure(id, subst) => TyKind::Closure(id, from_chalk(db, subst)),
|
||||
|
||||
chalk_ir::TyKind::Foreign(foreign_def_id) => TyKind::Foreign(foreign_def_id),
|
||||
chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME
|
||||
chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME
|
||||
}
|
||||
.intern(&Interner)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for GenericArg {
|
||||
type Chalk = chalk_ir::GenericArg<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
|
||||
match self.interned() {
|
||||
crate::GenericArgData::Ty(ty) => ty.clone().to_chalk(db).cast(&Interner),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
|
||||
match chalk.interned() {
|
||||
chalk_ir::GenericArgData::Ty(ty) => Ty::from_chalk(db, ty.clone()).cast(&Interner),
|
||||
chalk_ir::GenericArgData::Lifetime(_) => unimplemented!(),
|
||||
chalk_ir::GenericArgData::Const(_) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for Substitution {
|
||||
type Chalk = chalk_ir::Substitution<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> {
|
||||
chalk_ir::Substitution::from_iter(
|
||||
&Interner,
|
||||
self.iter(&Interner).map(|ty| ty.clone().to_chalk(db)),
|
||||
)
|
||||
}
|
||||
|
||||
fn from_chalk(
|
||||
db: &dyn HirDatabase,
|
||||
parameters: chalk_ir::Substitution<Interner>,
|
||||
) -> Substitution {
|
||||
let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect();
|
||||
Substitution::intern(tys)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for TraitRef {
|
||||
type Chalk = chalk_ir::TraitRef<Interner>;
|
||||
|
||||
fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> {
|
||||
let trait_id = self.trait_id;
|
||||
let substitution = self.substitution.to_chalk(db);
|
||||
chalk_ir::TraitRef { trait_id, substitution }
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self {
|
||||
let trait_id = trait_ref.trait_id;
|
||||
let substs = from_chalk(db, trait_ref.substitution);
|
||||
TraitRef { trait_id, substitution: substs }
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for hir_def::TraitId {
|
||||
type Chalk = TraitId;
|
||||
|
||||
|
@ -283,208 +70,6 @@ impl ToChalk for TypeAliasAsValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToChalk for WhereClause {
|
||||
type Chalk = chalk_ir::WhereClause<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> {
|
||||
match self {
|
||||
WhereClause::Implemented(trait_ref) => {
|
||||
chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db))
|
||||
}
|
||||
WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_chalk(
|
||||
db: &dyn HirDatabase,
|
||||
where_clause: chalk_ir::WhereClause<Interner>,
|
||||
) -> WhereClause {
|
||||
match where_clause {
|
||||
chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)),
|
||||
chalk_ir::WhereClause::AliasEq(alias_eq) => {
|
||||
WhereClause::AliasEq(from_chalk(db, alias_eq))
|
||||
}
|
||||
|
||||
chalk_ir::WhereClause::LifetimeOutlives(_) => {
|
||||
// we shouldn't get these from Chalk
|
||||
panic!("encountered LifetimeOutlives from Chalk")
|
||||
}
|
||||
|
||||
chalk_ir::WhereClause::TypeOutlives(_) => {
|
||||
// we shouldn't get these from Chalk
|
||||
panic!("encountered TypeOutlives from Chalk")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for ProjectionTy {
|
||||
type Chalk = chalk_ir::ProjectionTy<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> {
|
||||
chalk_ir::ProjectionTy {
|
||||
associated_ty_id: self.associated_ty_id,
|
||||
substitution: self.substitution.to_chalk(db),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_chalk(
|
||||
db: &dyn HirDatabase,
|
||||
projection_ty: chalk_ir::ProjectionTy<Interner>,
|
||||
) -> ProjectionTy {
|
||||
ProjectionTy {
|
||||
associated_ty_id: projection_ty.associated_ty_id,
|
||||
substitution: from_chalk(db, projection_ty.substitution),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ToChalk for OpaqueTy {
|
||||
type Chalk = chalk_ir::OpaqueTy<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
|
||||
chalk_ir::OpaqueTy {
|
||||
opaque_ty_id: self.opaque_ty_id,
|
||||
substitution: self.substitution.to_chalk(db),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
|
||||
OpaqueTy {
|
||||
opaque_ty_id: chalk.opaque_ty_id,
|
||||
substitution: from_chalk(db, chalk.substitution),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for AliasTy {
|
||||
type Chalk = chalk_ir::AliasTy<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
|
||||
match self {
|
||||
AliasTy::Projection(projection_ty) => {
|
||||
chalk_ir::AliasTy::Projection(projection_ty.to_chalk(db))
|
||||
}
|
||||
AliasTy::Opaque(opaque_ty) => chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
|
||||
match chalk {
|
||||
chalk_ir::AliasTy::Projection(projection_ty) => {
|
||||
AliasTy::Projection(from_chalk(db, projection_ty))
|
||||
}
|
||||
chalk_ir::AliasTy::Opaque(opaque_ty) => AliasTy::Opaque(from_chalk(db, opaque_ty)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for AliasEq {
|
||||
type Chalk = chalk_ir::AliasEq<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> {
|
||||
chalk_ir::AliasEq { alias: self.alias.to_chalk(db), ty: self.ty.to_chalk(db) }
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, alias_eq: chalk_ir::AliasEq<Interner>) -> Self {
|
||||
AliasEq { alias: from_chalk(db, alias_eq.alias), ty: from_chalk(db, alias_eq.ty) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for DomainGoal {
|
||||
type Chalk = chalk_ir::DomainGoal<Interner>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
|
||||
match self {
|
||||
DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner),
|
||||
DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => {
|
||||
alias_eq.to_chalk(db).cast(&Interner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_chalk(_db: &dyn HirDatabase, _goal: chalk_ir::DomainGoal<Interner>) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToChalk for Canonical<T>
|
||||
where
|
||||
T: ToChalk,
|
||||
T::Chalk: HasInterner<Interner = Interner>,
|
||||
{
|
||||
type Chalk = chalk_ir::Canonical<T::Chalk>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
|
||||
let value = self.value.to_chalk(db);
|
||||
chalk_ir::Canonical { value, binders: self.binders }
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
|
||||
Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToChalk> ToChalk for InEnvironment<T>
|
||||
where
|
||||
T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
|
||||
{
|
||||
type Chalk = chalk_ir::InEnvironment<T::Chalk>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
|
||||
chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) }
|
||||
}
|
||||
|
||||
fn from_chalk(
|
||||
_db: &dyn HirDatabase,
|
||||
_in_env: chalk_ir::InEnvironment<T::Chalk>,
|
||||
) -> InEnvironment<T> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToChalk> ToChalk for crate::Binders<T>
|
||||
where
|
||||
T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
|
||||
{
|
||||
type Chalk = chalk_ir::Binders<T::Chalk>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> {
|
||||
let (value, binders) = self.into_value_and_skipped_binders();
|
||||
chalk_ir::Binders::new(binders, value.to_chalk(db))
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> {
|
||||
let (v, b) = binders.into_value_and_skipped_binders();
|
||||
crate::Binders::new(b, from_chalk(db, v))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToChalk for crate::ConstrainedSubst {
|
||||
type Chalk = chalk_ir::ConstrainedSubst<Interner>;
|
||||
|
||||
fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
|
||||
ConstrainedSubst { subst: from_chalk(db, chalk.subst) }
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
|
||||
where
|
||||
T: HasInterner<Interner = Interner>,
|
||||
{
|
||||
chalk_ir::Binders::new(
|
||||
chalk_ir::VariableKinds::from_iter(
|
||||
&Interner,
|
||||
std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
|
||||
.take(num_vars),
|
||||
),
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn convert_where_clauses(
|
||||
db: &dyn HirDatabase,
|
||||
def: GenericDefId,
|
||||
|
@ -493,7 +78,7 @@ pub(super) fn convert_where_clauses(
|
|||
let generic_predicates = db.generic_predicates(def);
|
||||
let mut result = Vec::with_capacity(generic_predicates.len());
|
||||
for pred in generic_predicates.iter() {
|
||||
result.push(pred.clone().substitute(&Interner, substs).to_chalk(db));
|
||||
result.push(pred.clone().substitute(&Interner, substs));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
@ -505,7 +90,7 @@ pub(super) fn generic_predicate_to_inline_bound(
|
|||
) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
|
||||
// An InlineBound is like a GenericPredicate, except the self type is left out.
|
||||
// We don't have a special type for this, but Chalk does.
|
||||
let self_ty_shifted_in = self_ty.clone().shifted_in_from(DebruijnIndex::ONE);
|
||||
let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE);
|
||||
let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
|
||||
match pred {
|
||||
WhereClause::Implemented(trait_ref) => {
|
||||
|
@ -516,7 +101,7 @@ pub(super) fn generic_predicate_to_inline_bound(
|
|||
}
|
||||
let args_no_self = trait_ref.substitution.interned()[1..]
|
||||
.iter()
|
||||
.map(|ty| ty.clone().to_chalk(db).cast(&Interner))
|
||||
.map(|ty| ty.clone().cast(&Interner))
|
||||
.collect();
|
||||
let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
|
||||
Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
|
||||
|
@ -528,10 +113,10 @@ pub(super) fn generic_predicate_to_inline_bound(
|
|||
let trait_ = projection_ty.trait_(db);
|
||||
let args_no_self = projection_ty.substitution.interned()[1..]
|
||||
.iter()
|
||||
.map(|ty| ty.clone().to_chalk(db).cast(&Interner))
|
||||
.map(|ty| ty.clone().cast(&Interner))
|
||||
.collect();
|
||||
let alias_eq_bound = rust_ir::AliasEqBound {
|
||||
value: ty.clone().to_chalk(db),
|
||||
value: ty.clone(),
|
||||
trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self },
|
||||
associated_ty_id: projection_ty.associated_ty_id,
|
||||
parameters: Vec::new(), // FIXME we don't support generic associated types yet
|
||||
|
|
|
@ -1,549 +0,0 @@
|
|||
//! This is the home of `Ty` etc. until they get replaced by their chalk_ir
|
||||
//! equivalents.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use chalk_ir::{
|
||||
cast::{Cast, CastTo, Caster},
|
||||
BoundVar, Mutability, Scalar, TyVariableKind,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{
|
||||
AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, Const, FnDefId, FnSig, ForeignDefId,
|
||||
Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, VariableKinds,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct OpaqueTy {
|
||||
pub opaque_ty_id: OpaqueTyId,
|
||||
pub substitution: Substitution,
|
||||
}
|
||||
|
||||
/// A "projection" type corresponds to an (unnormalized)
|
||||
/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
|
||||
/// trait and all its parameters are fully known.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct ProjectionTy {
|
||||
pub associated_ty_id: AssocTypeId,
|
||||
pub substitution: Substitution,
|
||||
}
|
||||
|
||||
impl ProjectionTy {
|
||||
pub fn self_type_parameter(&self, interner: &Interner) -> Ty {
|
||||
self.substitution.interned()[0].assert_ty_ref(interner).clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct DynTy {
|
||||
/// The unknown self type.
|
||||
pub bounds: Binders<QuantifiedWhereClauses>,
|
||||
pub lifetime: Lifetime,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct FnPointer {
|
||||
pub num_binders: usize,
|
||||
pub sig: FnSig,
|
||||
pub substitution: FnSubst,
|
||||
}
|
||||
/// A wrapper for the substs on a Fn.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct FnSubst(pub Substitution);
|
||||
|
||||
impl FnPointer {
|
||||
/// Represent the current `Fn` as if it was wrapped in `Binders`
|
||||
pub fn into_binders(self, interner: &Interner) -> Binders<FnSubst> {
|
||||
Binders::new(
|
||||
VariableKinds::from_iter(
|
||||
interner,
|
||||
(0..self.num_binders).map(|_| VariableKind::Lifetime),
|
||||
),
|
||||
self.substitution,
|
||||
)
|
||||
}
|
||||
|
||||
/// Represent the current `Fn` as if it was wrapped in `Binders`
|
||||
pub fn as_binders(&self, interner: &Interner) -> Binders<&FnSubst> {
|
||||
Binders::new(
|
||||
VariableKinds::from_iter(
|
||||
interner,
|
||||
(0..self.num_binders).map(|_| VariableKind::Lifetime),
|
||||
),
|
||||
&self.substitution,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum AliasTy {
|
||||
/// A "projection" type corresponds to an (unnormalized)
|
||||
/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
|
||||
/// trait and all its parameters are fully known.
|
||||
Projection(ProjectionTy),
|
||||
/// An opaque type (`impl Trait`).
|
||||
///
|
||||
/// This is currently only used for return type impl trait; each instance of
|
||||
/// `impl Trait` in a return type gets its own ID.
|
||||
Opaque(OpaqueTy),
|
||||
}
|
||||
|
||||
/// A type.
|
||||
///
|
||||
/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
|
||||
/// the same thing (but in a different way).
|
||||
///
|
||||
/// This should be cheap to clone.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum TyKind {
|
||||
/// Structures, enumerations and unions.
|
||||
Adt(chalk_ir::AdtId<Interner>, Substitution),
|
||||
|
||||
/// Represents an associated item like `Iterator::Item`. This is used
|
||||
/// when we have tried to normalize a projection like `T::Item` but
|
||||
/// couldn't find a better representation. In that case, we generate
|
||||
/// an **application type** like `(Iterator::Item)<T>`.
|
||||
AssociatedType(AssocTypeId, Substitution),
|
||||
|
||||
/// a scalar type like `bool` or `u32`
|
||||
Scalar(Scalar),
|
||||
|
||||
/// A tuple type. For example, `(i32, bool)`.
|
||||
Tuple(usize, Substitution),
|
||||
|
||||
/// An array with the given length. Written as `[T; n]`.
|
||||
Array(Ty, Const),
|
||||
|
||||
/// The pointee of an array slice. Written as `[T]`.
|
||||
Slice(Ty),
|
||||
|
||||
/// A raw pointer. Written as `*mut T` or `*const T`
|
||||
Raw(Mutability, Ty),
|
||||
|
||||
/// A reference; a pointer with an associated lifetime. Written as
|
||||
/// `&'a mut T` or `&'a T`.
|
||||
Ref(Mutability, Lifetime, Ty),
|
||||
|
||||
/// This represents a placeholder for an opaque type in situations where we
|
||||
/// don't know the hidden type (i.e. currently almost always). This is
|
||||
/// analogous to the `AssociatedType` type constructor.
|
||||
/// It is also used as the type of async block, with one type parameter
|
||||
/// representing the Future::Output type.
|
||||
OpaqueType(OpaqueTyId, Substitution),
|
||||
|
||||
/// The anonymous type of a function declaration/definition. Each
|
||||
/// function has a unique type, which is output (for a function
|
||||
/// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
|
||||
///
|
||||
/// This includes tuple struct / enum variant constructors as well.
|
||||
///
|
||||
/// For example the type of `bar` here:
|
||||
///
|
||||
/// ```
|
||||
/// fn foo() -> i32 { 1 }
|
||||
/// let bar = foo; // bar: fn() -> i32 {foo}
|
||||
/// ```
|
||||
FnDef(FnDefId, Substitution),
|
||||
|
||||
/// The pointee of a string slice. Written as `str`.
|
||||
Str,
|
||||
|
||||
/// The never type `!`.
|
||||
Never,
|
||||
|
||||
/// The type of a specific closure.
|
||||
///
|
||||
/// The closure signature is stored in a `FnPtr` type in the first type
|
||||
/// parameter.
|
||||
Closure(ClosureId, Substitution),
|
||||
|
||||
/// Represents a foreign type declared in external blocks.
|
||||
Foreign(ForeignDefId),
|
||||
|
||||
/// A pointer to a function. Written as `fn() -> i32`.
|
||||
///
|
||||
/// For example the type of `bar` here:
|
||||
///
|
||||
/// ```
|
||||
/// fn foo() -> i32 { 1 }
|
||||
/// let bar: fn() -> i32 = foo;
|
||||
/// ```
|
||||
Function(FnPointer),
|
||||
|
||||
/// An "alias" type represents some form of type alias, such as:
|
||||
/// - An associated type projection like `<T as Iterator>::Item`
|
||||
/// - `impl Trait` types
|
||||
/// - Named type aliases like `type Foo<X> = Vec<X>`
|
||||
Alias(AliasTy),
|
||||
|
||||
/// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T)
|
||||
/// {}` when we're type-checking the body of that function. In this
|
||||
/// situation, we know this stands for *some* type, but don't know the exact
|
||||
/// type.
|
||||
Placeholder(PlaceholderIndex),
|
||||
|
||||
/// A bound type variable. This is used in various places: when representing
|
||||
/// some polymorphic type like the type of function `fn f<T>`, the type
|
||||
/// parameters get turned into variables; during trait resolution, inference
|
||||
/// variables get turned into bound variables and back; and in `Dyn` the
|
||||
/// `Self` type is represented with a bound variable as well.
|
||||
BoundVar(BoundVar),
|
||||
|
||||
/// A type variable used during type checking.
|
||||
InferenceVar(InferenceVar, TyVariableKind),
|
||||
|
||||
/// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
|
||||
///
|
||||
/// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
|
||||
/// represents the `Self` type inside the bounds. This is currently
|
||||
/// implicit; Chalk has the `Binders` struct to make it explicit, but it
|
||||
/// didn't seem worth the overhead yet.
|
||||
Dyn(DynTy),
|
||||
|
||||
/// A placeholder for a type which could not be computed; this is propagated
|
||||
/// to avoid useless error messages. Doubles as a placeholder where type
|
||||
/// variables are inserted before type checking, since we want to try to
|
||||
/// infer a better type here anyway -- for the IDE use case, we want to try
|
||||
/// to infer as much as possible even in the presence of type errors.
|
||||
Error,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct Ty(Arc<TyKind>);
|
||||
|
||||
impl TyKind {
|
||||
pub fn intern(self, _interner: &Interner) -> Ty {
|
||||
Ty(Arc::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ty {
|
||||
pub fn kind(&self, _interner: &Interner) -> &TyKind {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn interned_mut(&mut self) -> &mut TyKind {
|
||||
Arc::make_mut(&mut self.0)
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> TyKind {
|
||||
Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct GenericArg {
|
||||
interned: GenericArgData,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum GenericArgData {
|
||||
Ty(Ty),
|
||||
}
|
||||
|
||||
impl GenericArg {
|
||||
/// Constructs a generic argument using `GenericArgData`.
|
||||
pub fn new(_interner: &Interner, data: GenericArgData) -> Self {
|
||||
GenericArg { interned: data }
|
||||
}
|
||||
|
||||
/// Gets the interned value.
|
||||
pub fn interned(&self) -> &GenericArgData {
|
||||
&self.interned
|
||||
}
|
||||
|
||||
/// Asserts that this is a type argument.
|
||||
pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty {
|
||||
self.ty(interner).unwrap()
|
||||
}
|
||||
|
||||
/// Checks whether the generic argument is a type.
|
||||
pub fn is_ty(&self, _interner: &Interner) -> bool {
|
||||
match self.interned() {
|
||||
GenericArgData::Ty(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the type if it is one, `None` otherwise.
|
||||
pub fn ty(&self, _interner: &Interner) -> Option<&Ty> {
|
||||
match self.interned() {
|
||||
GenericArgData::Ty(t) => Some(t),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interned_mut(&mut self) -> &mut GenericArgData {
|
||||
&mut self.interned
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of substitutions for generic parameters.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct Substitution(SmallVec<[GenericArg; 2]>);
|
||||
|
||||
impl Substitution {
|
||||
pub fn interned(&self) -> &SmallVec<[GenericArg; 2]> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn len(&self, _: &Interner) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self, _: &Interner) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
pub fn at(&self, _: &Interner, i: usize) -> &GenericArg {
|
||||
&self.0[i]
|
||||
}
|
||||
|
||||
pub fn empty(_: &Interner) -> Substitution {
|
||||
Substitution(SmallVec::new())
|
||||
}
|
||||
|
||||
pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
pub fn from1(_interner: &Interner, ty: Ty) -> Substitution {
|
||||
Substitution::intern({
|
||||
let mut v = SmallVec::new();
|
||||
v.push(ty.cast(&Interner));
|
||||
v
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_iter(
|
||||
interner: &Interner,
|
||||
elements: impl IntoIterator<Item = impl CastTo<GenericArg>>,
|
||||
) -> Self {
|
||||
Substitution(elements.into_iter().casted(interner).collect())
|
||||
}
|
||||
|
||||
pub fn apply<T: TypeWalk>(&self, value: T, _interner: &Interner) -> T {
|
||||
value.subst_bound_vars(self)
|
||||
}
|
||||
|
||||
// Temporary helper functions, to be removed
|
||||
pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution {
|
||||
Substitution(interned)
|
||||
}
|
||||
|
||||
pub fn interned_mut(&mut self) -> &mut SmallVec<[GenericArg; 2]> {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Binders<T> {
|
||||
/// The binders that quantify over the value.
|
||||
pub binders: VariableKinds,
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl<T> Binders<T> {
|
||||
pub fn new(binders: VariableKinds, value: T) -> Self {
|
||||
Self { binders, value }
|
||||
}
|
||||
|
||||
pub fn empty(_interner: &Interner, value: T) -> Self {
|
||||
crate::make_only_type_binders(0, value)
|
||||
}
|
||||
|
||||
pub fn as_ref(&self) -> Binders<&T> {
|
||||
Binders { binders: self.binders.clone(), value: &self.value }
|
||||
}
|
||||
|
||||
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Binders<U> {
|
||||
Binders { binders: self.binders, value: f(self.value) }
|
||||
}
|
||||
|
||||
pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> {
|
||||
Some(Binders { binders: self.binders, value: f(self.value)? })
|
||||
}
|
||||
|
||||
pub fn skip_binders(&self) -> &T {
|
||||
&self.value
|
||||
}
|
||||
|
||||
pub fn into_value_and_skipped_binders(self) -> (T, VariableKinds) {
|
||||
(self.value, self.binders)
|
||||
}
|
||||
|
||||
/// Returns the number of binders.
|
||||
pub fn len(&self, interner: &Interner) -> usize {
|
||||
self.binders.len(interner)
|
||||
}
|
||||
|
||||
// Temporary helper function, to be removed
|
||||
pub fn skip_binders_mut(&mut self) -> &mut T {
|
||||
&mut self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Binders<&T> {
|
||||
pub fn cloned(&self) -> Binders<T> {
|
||||
Binders::new(self.binders.clone(), self.value.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TypeWalk> Binders<T> {
|
||||
/// Substitutes all variables.
|
||||
pub fn substitute(self, interner: &Interner, subst: &Substitution) -> T {
|
||||
let (value, binders) = self.into_value_and_skipped_binders();
|
||||
assert_eq!(subst.len(interner), binders.len(interner));
|
||||
value.subst_bound_vars(subst)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: std::fmt::Debug> std::fmt::Debug for Binders<T> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
let Binders { ref binders, ref value } = *self;
|
||||
write!(fmt, "for{:?} ", binders.inner_debug(&Interner))?;
|
||||
std::fmt::Debug::fmt(value, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct TraitRef {
|
||||
pub trait_id: ChalkTraitId,
|
||||
pub substitution: Substitution,
|
||||
}
|
||||
|
||||
impl TraitRef {
|
||||
pub fn self_type_parameter(&self, interner: &Interner) -> Ty {
|
||||
self.substitution.at(interner, 0).assert_ty_ref(interner).clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `generics::WherePredicate`, but with resolved types: A condition on the
|
||||
/// parameters of a generic item.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum WhereClause {
|
||||
/// The given trait needs to be implemented for its type parameters.
|
||||
Implemented(TraitRef),
|
||||
/// An associated type bindings like in `Iterator<Item = T>`.
|
||||
AliasEq(AliasEq),
|
||||
}
|
||||
|
||||
pub type QuantifiedWhereClause = Binders<WhereClause>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
|
||||
|
||||
impl QuantifiedWhereClauses {
|
||||
pub fn from_iter(
|
||||
_interner: &Interner,
|
||||
elements: impl IntoIterator<Item = QuantifiedWhereClause>,
|
||||
) -> Self {
|
||||
QuantifiedWhereClauses(elements.into_iter().collect())
|
||||
}
|
||||
|
||||
pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn interned_mut(&mut self) -> &mut Arc<[QuantifiedWhereClause]> {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Basically a claim (currently not validated / checked) that the contained
|
||||
/// type / trait ref contains no inference variables; any inference variables it
|
||||
/// contained have been replaced by bound variables, and `kinds` tells us how
|
||||
/// many there are and whether they were normal or float/int variables. This is
|
||||
/// used to erase irrelevant differences between types before using them in
|
||||
/// queries.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Canonical<T> {
|
||||
pub value: T,
|
||||
pub binders: CanonicalVarKinds,
|
||||
}
|
||||
|
||||
/// Something (usually a goal), along with an environment.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct InEnvironment<T> {
|
||||
pub environment: chalk_ir::Environment<Interner>,
|
||||
pub goal: T,
|
||||
}
|
||||
|
||||
impl<T> InEnvironment<T> {
|
||||
pub fn new(environment: &chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> {
|
||||
InEnvironment { environment: environment.clone(), goal: value }
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that needs to be proven (by Chalk) during type checking, e.g. that
|
||||
/// a certain type implements a certain trait. Proving the Obligation might
|
||||
/// result in additional information about inference variables.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum DomainGoal {
|
||||
Holds(WhereClause),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct AliasEq {
|
||||
pub alias: AliasTy,
|
||||
pub ty: Ty,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ConstrainedSubst {
|
||||
pub subst: Substitution,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
/// A (possible) solution for a proposed goal.
|
||||
pub enum Solution {
|
||||
/// The goal indeed holds, and there is a unique value for all existential
|
||||
/// variables.
|
||||
Unique(Canonical<ConstrainedSubst>),
|
||||
|
||||
/// The goal may be provable in multiple ways, but regardless we may have some guidance
|
||||
/// for type inference. In this case, we don't return any lifetime
|
||||
/// constraints, since we have not "committed" to any particular solution
|
||||
/// yet.
|
||||
Ambig(Guidance),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
/// When a goal holds ambiguously (e.g., because there are multiple possible
|
||||
/// solutions), we issue a set of *guidance* back to type inference.
|
||||
pub enum Guidance {
|
||||
/// The existential variables *must* have the given values if the goal is
|
||||
/// ever to hold, but that alone isn't enough to guarantee the goal will
|
||||
/// actually hold.
|
||||
Definite(Canonical<Substitution>),
|
||||
|
||||
/// There are multiple plausible values for the existentials, but the ones
|
||||
/// here are suggested as the preferred choice heuristically. These should
|
||||
/// be used for inference fallback only.
|
||||
Suggested(Canonical<Substitution>),
|
||||
|
||||
/// There's no useful information to feed back to type inference
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// The kinds of placeholders we need during type inference. There's separate
|
||||
/// values for general types, and for integer and float variables. The latter
|
||||
/// two are used for inference of literal values (e.g. `100` could be one of
|
||||
/// several integer types).
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct InferenceVar {
|
||||
index: u32,
|
||||
}
|
||||
|
||||
impl From<u32> for InferenceVar {
|
||||
fn from(index: u32) -> InferenceVar {
|
||||
InferenceVar { index }
|
||||
}
|
||||
}
|
||||
|
||||
impl InferenceVar {
|
||||
/// Gets the underlying index value.
|
||||
pub fn index(self) -> u32 {
|
||||
self.index
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
//! Helper functions for working with def, which don't need to be a separate
|
||||
//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
|
||||
use std::sync::Arc;
|
||||
|
||||
use chalk_ir::{BoundVar, DebruijnIndex};
|
||||
use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex};
|
||||
use hir_def::{
|
||||
db::DefDatabase,
|
||||
generics::{
|
||||
|
@ -16,9 +15,7 @@ use hir_def::{
|
|||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, Interner, Substitution, TraitRef, TraitRefExt, TyKind, TypeWalk, WhereClause,
|
||||
};
|
||||
use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TraitRefExt, TyKind, WhereClause};
|
||||
|
||||
fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
|
||||
let resolver = trait_.resolver(db);
|
||||
|
@ -69,7 +66,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
|
|||
// FIXME: how to correctly handle higher-ranked bounds here?
|
||||
WhereClause::Implemented(tr) => Some(
|
||||
tr.clone()
|
||||
.shifted_out_to(DebruijnIndex::ONE)
|
||||
.shifted_out_to(&Interner, DebruijnIndex::ONE)
|
||||
.expect("FIXME unexpected higher-ranked trait bound"),
|
||||
),
|
||||
_ => None,
|
||||
|
@ -137,15 +134,6 @@ pub(super) fn associated_type_by_name_including_super_traits(
|
|||
})
|
||||
}
|
||||
|
||||
/// Helper for mutating `Arc<[T]>` (i.e. `Arc::make_mut` for Arc slices).
|
||||
/// The underlying values are cloned if there are other strong references.
|
||||
pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
|
||||
if Arc::get_mut(a).is_none() {
|
||||
*a = a.iter().cloned().collect();
|
||||
}
|
||||
Arc::get_mut(a).unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
|
||||
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
|
||||
Generics { def, params: db.generic_params(def), parent_generics }
|
||||
|
|
|
@ -1,138 +1,17 @@
|
|||
//! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and
|
||||
//! `Visit`).
|
||||
|
||||
use std::mem;
|
||||
|
||||
use chalk_ir::DebruijnIndex;
|
||||
use chalk_ir::interner::HasInterner;
|
||||
|
||||
use crate::{
|
||||
utils::make_mut_slice, AliasEq, AliasTy, Binders, CallableSig, FnSubst, GenericArg,
|
||||
GenericArgData, Interner, OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind,
|
||||
WhereClause,
|
||||
AliasEq, AliasTy, Binders, CallableSig, FnSubst, GenericArg, GenericArgData, Interner,
|
||||
OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause,
|
||||
};
|
||||
|
||||
/// This allows walking structures that contain types to do something with those
|
||||
/// types, similar to Chalk's `Fold` trait.
|
||||
pub trait TypeWalk {
|
||||
fn walk(&self, f: &mut impl FnMut(&Ty));
|
||||
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
||||
self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST);
|
||||
}
|
||||
/// Walk the type, counting entered binders.
|
||||
///
|
||||
/// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers
|
||||
/// to the innermost binder, 1 to the next, etc.. So when we want to
|
||||
/// substitute a certain bound variable, we can't just walk the whole type
|
||||
/// and blindly replace each instance of a certain index; when we 'enter'
|
||||
/// things that introduce new bound variables, we have to keep track of
|
||||
/// that. Currently, the only thing that introduces bound variables on our
|
||||
/// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound
|
||||
/// variable for the self type.
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
);
|
||||
|
||||
fn fold_binders(
|
||||
mut self,
|
||||
f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty,
|
||||
binders: DebruijnIndex,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.walk_mut_binders(
|
||||
&mut |ty_mut, binders| {
|
||||
let ty = mem::replace(ty_mut, TyKind::Error.intern(&Interner));
|
||||
*ty_mut = f(ty, binders);
|
||||
},
|
||||
binders,
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.walk_mut(&mut |ty_mut| {
|
||||
let ty = mem::replace(ty_mut, TyKind::Error.intern(&Interner));
|
||||
*ty_mut = f(ty);
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
/// Substitutes `TyKind::Bound` vars with the given substitution.
|
||||
fn subst_bound_vars(self, substs: &Substitution) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
|
||||
}
|
||||
|
||||
/// Substitutes `TyKind::Bound` vars with the given substitution.
|
||||
fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.walk_mut_binders(
|
||||
&mut |ty, binders| {
|
||||
if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
|
||||
if bound.debruijn >= binders {
|
||||
*ty = substs.interned()[bound.index]
|
||||
.assert_ty_ref(&Interner)
|
||||
.clone()
|
||||
.shifted_in_from(binders);
|
||||
}
|
||||
}
|
||||
},
|
||||
depth,
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
fn shifted_in(self, _interner: &Interner) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.shifted_in_from(DebruijnIndex::ONE)
|
||||
}
|
||||
|
||||
/// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
|
||||
fn shifted_in_from(self, n: DebruijnIndex) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.fold_binders(
|
||||
&mut |ty, binders| match ty.kind(&Interner) {
|
||||
TyKind::BoundVar(bound) if bound.debruijn >= binders => {
|
||||
TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
|
||||
}
|
||||
_ => ty,
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
}
|
||||
|
||||
/// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`.
|
||||
fn shifted_out_to(self, n: DebruijnIndex) -> Option<Self>
|
||||
where
|
||||
Self: Sized + std::fmt::Debug,
|
||||
{
|
||||
Some(self.fold_binders(
|
||||
&mut |ty, binders| {
|
||||
match ty.kind(&Interner) {
|
||||
TyKind::BoundVar(bound) if bound.debruijn >= binders => {
|
||||
TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone()))
|
||||
.intern(&Interner)
|
||||
}
|
||||
_ => ty,
|
||||
}
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for Ty {
|
||||
|
@ -174,45 +53,6 @@ impl TypeWalk for Ty {
|
|||
}
|
||||
f(self);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
match self.interned_mut() {
|
||||
TyKind::Alias(AliasTy::Projection(p_ty)) => {
|
||||
p_ty.substitution.walk_mut_binders(f, binders);
|
||||
}
|
||||
TyKind::Dyn(dyn_ty) => {
|
||||
for p in make_mut_slice(dyn_ty.bounds.skip_binders_mut().interned_mut()) {
|
||||
p.walk_mut_binders(f, binders.shifted_in());
|
||||
}
|
||||
}
|
||||
TyKind::Alias(AliasTy::Opaque(o_ty)) => {
|
||||
o_ty.substitution.walk_mut_binders(f, binders);
|
||||
}
|
||||
TyKind::Slice(ty)
|
||||
| TyKind::Array(ty, _)
|
||||
| TyKind::Ref(_, _, ty)
|
||||
| TyKind::Raw(_, ty) => {
|
||||
ty.walk_mut_binders(f, binders);
|
||||
}
|
||||
TyKind::Function(fn_pointer) => {
|
||||
fn_pointer.substitution.0.walk_mut_binders(f, binders.shifted_in());
|
||||
}
|
||||
TyKind::Adt(_, substs)
|
||||
| TyKind::FnDef(_, substs)
|
||||
| TyKind::Tuple(_, substs)
|
||||
| TyKind::OpaqueType(_, substs)
|
||||
| TyKind::AssociatedType(_, substs)
|
||||
| TyKind::Closure(.., substs) => {
|
||||
substs.walk_mut_binders(f, binders);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
f(self, binders);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TypeWalk> TypeWalk for Vec<T> {
|
||||
|
@ -221,43 +61,18 @@ impl<T: TypeWalk> TypeWalk for Vec<T> {
|
|||
t.walk(f);
|
||||
}
|
||||
}
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
for t in self {
|
||||
t.walk_mut_binders(f, binders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for OpaqueTy {
|
||||
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||
self.substitution.walk(f);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.substitution.walk_mut_binders(f, binders);
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for ProjectionTy {
|
||||
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||
self.substitution.walk(f);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.substitution.walk_mut_binders(f, binders);
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for AliasTy {
|
||||
|
@ -267,17 +82,6 @@ impl TypeWalk for AliasTy {
|
|||
AliasTy::Opaque(it) => it.walk(f),
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
match self {
|
||||
AliasTy::Projection(it) => it.walk_mut_binders(f, binders),
|
||||
AliasTy::Opaque(it) => it.walk_mut_binders(f, binders),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for GenericArg {
|
||||
|
@ -286,18 +90,7 @@ impl TypeWalk for GenericArg {
|
|||
GenericArgData::Ty(ty) => {
|
||||
ty.walk(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
match self.interned_mut() {
|
||||
GenericArgData::Ty(ty) => {
|
||||
ty.walk_mut_binders(f, binders);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,44 +101,18 @@ impl TypeWalk for Substitution {
|
|||
t.walk(f);
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
for t in self.interned_mut() {
|
||||
t.walk_mut_binders(f, binders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TypeWalk> TypeWalk for Binders<T> {
|
||||
impl<T: TypeWalk + HasInterner<Interner = Interner>> TypeWalk for Binders<T> {
|
||||
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||
self.skip_binders().walk(f);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.skip_binders_mut().walk_mut_binders(f, binders.shifted_in())
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for TraitRef {
|
||||
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||
self.substitution.walk(f);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.substitution.walk_mut_binders(f, binders);
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for WhereClause {
|
||||
|
@ -353,17 +120,7 @@ impl TypeWalk for WhereClause {
|
|||
match self {
|
||||
WhereClause::Implemented(trait_ref) => trait_ref.walk(f),
|
||||
WhereClause::AliasEq(alias_eq) => alias_eq.walk(f),
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
match self {
|
||||
WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
|
||||
WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,16 +131,6 @@ impl TypeWalk for CallableSig {
|
|||
t.walk(f);
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
for t in make_mut_slice(&mut self.params_and_return) {
|
||||
t.walk_mut_binders(f, binders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for AliasEq {
|
||||
|
@ -394,30 +141,10 @@ impl TypeWalk for AliasEq {
|
|||
AliasTy::Opaque(opaque) => opaque.walk(f),
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.ty.walk_mut_binders(f, binders);
|
||||
match &mut self.alias {
|
||||
AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders),
|
||||
AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeWalk for FnSubst {
|
||||
impl TypeWalk for FnSubst<Interner> {
|
||||
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||
self.0.walk(f)
|
||||
}
|
||||
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.0.walk_mut_binders(f, binders)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ env_logger = { version = "0.8.1", default-features = false }
|
|||
itertools = "0.10.0"
|
||||
jod-thread = "0.1.0"
|
||||
log = "0.4.8"
|
||||
lsp-types = { version = "0.88.0", features = ["proposed"] }
|
||||
lsp-types = { version = "0.89.0", features = ["proposed"] }
|
||||
parking_lot = "0.11.0"
|
||||
xflags = "0.2.1"
|
||||
oorandom = "11.1.2"
|
||||
|
|
Loading…
Reference in a new issue