mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 07:04:22 +00:00
Upgrade Chalk again
The big change here is counting binders, not variables (https://github.com/rust-lang/chalk/pull/360). We have to adapt to the same scheme for our `Ty::Bound`. It's mostly fine though, even makes some things more clear.
This commit is contained in:
parent
3659502816
commit
952714685a
12 changed files with 197 additions and 114 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -114,7 +114,7 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|||
[[package]]
|
||||
name = "chalk-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=d383af7333cc6014e9d9e3e77668b5d5b0a5b40e#d383af7333cc6014e9d9e3e77668b5d5b0a5b40e"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=039fc904a05f8cb3d0c682c9a57a63dda7a35356#039fc904a05f8cb3d0c682c9a57a63dda7a35356"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -124,7 +124,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "chalk-engine"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=d383af7333cc6014e9d9e3e77668b5d5b0a5b40e#d383af7333cc6014e9d9e3e77668b5d5b0a5b40e"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=039fc904a05f8cb3d0c682c9a57a63dda7a35356#039fc904a05f8cb3d0c682c9a57a63dda7a35356"
|
||||
dependencies = [
|
||||
"chalk-macros",
|
||||
"rustc-hash",
|
||||
|
@ -133,7 +133,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "chalk-ir"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=d383af7333cc6014e9d9e3e77668b5d5b0a5b40e#d383af7333cc6014e9d9e3e77668b5d5b0a5b40e"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=039fc904a05f8cb3d0c682c9a57a63dda7a35356#039fc904a05f8cb3d0c682c9a57a63dda7a35356"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-engine",
|
||||
|
@ -143,7 +143,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "chalk-macros"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=d383af7333cc6014e9d9e3e77668b5d5b0a5b40e#d383af7333cc6014e9d9e3e77668b5d5b0a5b40e"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=039fc904a05f8cb3d0c682c9a57a63dda7a35356#039fc904a05f8cb3d0c682c9a57a63dda7a35356"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
@ -151,7 +151,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "chalk-rust-ir"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=d383af7333cc6014e9d9e3e77668b5d5b0a5b40e#d383af7333cc6014e9d9e3e77668b5d5b0a5b40e"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=039fc904a05f8cb3d0c682c9a57a63dda7a35356#039fc904a05f8cb3d0c682c9a57a63dda7a35356"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-engine",
|
||||
|
@ -162,7 +162,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "chalk-solve"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=d383af7333cc6014e9d9e3e77668b5d5b0a5b40e#d383af7333cc6014e9d9e3e77668b5d5b0a5b40e"
|
||||
source = "git+https://github.com/rust-lang/chalk.git?rev=039fc904a05f8cb3d0c682c9a57a63dda7a35356#039fc904a05f8cb3d0c682c9a57a63dda7a35356"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-engine",
|
||||
|
|
|
@ -23,9 +23,9 @@ ra_prof = { path = "../ra_prof" }
|
|||
ra_syntax = { path = "../ra_syntax" }
|
||||
test_utils = { path = "../test_utils" }
|
||||
|
||||
chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "d383af7333cc6014e9d9e3e77668b5d5b0a5b40e" }
|
||||
chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "d383af7333cc6014e9d9e3e77668b5d5b0a5b40e" }
|
||||
chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "d383af7333cc6014e9d9e3e77668b5d5b0a5b40e" }
|
||||
chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
|
||||
chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
|
||||
chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
|
||||
|
||||
[dev-dependencies]
|
||||
insta = "0.15.0"
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
db::HirDatabase,
|
||||
traits::{InEnvironment, Solution},
|
||||
utils::generics,
|
||||
Canonical, Substs, Ty, TypeWalk,
|
||||
BoundVar, Canonical, DebruijnIndex, Substs, Ty,
|
||||
};
|
||||
|
||||
const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
||||
|
@ -61,14 +61,13 @@ fn deref_by_trait(
|
|||
return None;
|
||||
}
|
||||
|
||||
// FIXME make the Canonical handling nicer
|
||||
// FIXME make the Canonical / bound var handling nicer
|
||||
|
||||
let parameters = Substs::build_for_generics(&generic_params)
|
||||
.push(ty.value.value.clone().shift_bound_vars(1))
|
||||
.build();
|
||||
let parameters =
|
||||
Substs::build_for_generics(&generic_params).push(ty.value.value.clone()).build();
|
||||
|
||||
let projection = super::traits::ProjectionPredicate {
|
||||
ty: Ty::Bound(0),
|
||||
ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.num_vars)),
|
||||
projection_ty: super::ProjectionTy { associated_ty: target, parameters },
|
||||
};
|
||||
|
||||
|
@ -93,12 +92,16 @@ fn deref_by_trait(
|
|||
// we have `impl<T> Deref for Foo<T> { Target = T }`, that should be
|
||||
// the case.
|
||||
for i in 1..vars.0.num_vars {
|
||||
if vars.0.value[i] != Ty::Bound((i - 1) as u32) {
|
||||
if vars.0.value[i - 1] != Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
|
||||
{
|
||||
warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars })
|
||||
Some(Canonical {
|
||||
value: vars.0.value[vars.0.value.len() - 1].clone(),
|
||||
num_vars: vars.0.num_vars,
|
||||
})
|
||||
}
|
||||
Solution::Ambig(_) => {
|
||||
info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution);
|
||||
|
|
|
@ -303,7 +303,7 @@ impl HirDisplay for Ty {
|
|||
}
|
||||
}
|
||||
}
|
||||
Ty::Bound(idx) => write!(f, "?{}", idx)?,
|
||||
Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
|
||||
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
||||
match self {
|
||||
Ty::Dyn(_) => write!(f, "dyn ")?,
|
||||
|
|
|
@ -7,7 +7,9 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
|||
use test_utils::tested_by;
|
||||
|
||||
use super::{InferenceContext, Obligation};
|
||||
use crate::{Canonical, InEnvironment, InferTy, Substs, Ty, TypeCtor, TypeWalk};
|
||||
use crate::{
|
||||
BoundVar, Canonical, DebruijnIndex, InEnvironment, InferTy, Substs, Ty, TypeCtor, TypeWalk,
|
||||
};
|
||||
|
||||
impl<'a> InferenceContext<'a> {
|
||||
pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b>
|
||||
|
@ -47,7 +49,7 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: usize) -> T {
|
||||
fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
|
||||
t.fold_binders(
|
||||
&mut |ty, binders| match ty {
|
||||
Ty::Infer(tv) => {
|
||||
|
@ -72,7 +74,7 @@ where
|
|||
InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root),
|
||||
};
|
||||
let position = self.add(free_var);
|
||||
Ty::Bound((position + binders) as u32)
|
||||
Ty::Bound(BoundVar::new(binders, position))
|
||||
}
|
||||
}
|
||||
_ => ty,
|
||||
|
@ -89,7 +91,7 @@ where
|
|||
}
|
||||
|
||||
pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
|
||||
let result = self.do_canonicalize(ty, 0);
|
||||
let result = self.do_canonicalize(ty, DebruijnIndex::INNERMOST);
|
||||
self.into_canonicalized(result)
|
||||
}
|
||||
|
||||
|
@ -98,8 +100,12 @@ where
|
|||
obligation: InEnvironment<Obligation>,
|
||||
) -> Canonicalized<InEnvironment<Obligation>> {
|
||||
let result = match obligation.value {
|
||||
Obligation::Trait(tr) => Obligation::Trait(self.do_canonicalize(tr, 0)),
|
||||
Obligation::Projection(pr) => Obligation::Projection(self.do_canonicalize(pr, 0)),
|
||||
Obligation::Trait(tr) => {
|
||||
Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST))
|
||||
}
|
||||
Obligation::Projection(pr) => {
|
||||
Obligation::Projection(self.do_canonicalize(pr, DebruijnIndex::INNERMOST))
|
||||
}
|
||||
};
|
||||
self.into_canonicalized(InEnvironment {
|
||||
value: result,
|
||||
|
@ -112,13 +118,13 @@ impl<T> Canonicalized<T> {
|
|||
pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
|
||||
ty.walk_mut_binders(
|
||||
&mut |ty, binders| {
|
||||
if let &mut Ty::Bound(idx) = ty {
|
||||
if idx as usize >= binders && (idx as usize - binders) < self.free_vars.len() {
|
||||
*ty = Ty::Infer(self.free_vars[idx as usize - binders]);
|
||||
if let &mut Ty::Bound(bound) = ty {
|
||||
if bound.debruijn >= binders {
|
||||
*ty = Ty::Infer(self.free_vars[bound.index]);
|
||||
}
|
||||
}
|
||||
},
|
||||
0,
|
||||
DebruijnIndex::INNERMOST,
|
||||
);
|
||||
ty
|
||||
}
|
||||
|
@ -150,7 +156,7 @@ pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
|
|||
// (kind of hacky)
|
||||
for (i, var) in vars.iter().enumerate() {
|
||||
if &*table.resolve_ty_shallow(var) == var {
|
||||
table.unify(var, &Ty::Bound(i as u32));
|
||||
table.unify(var, &Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i)));
|
||||
}
|
||||
}
|
||||
Some(
|
||||
|
|
|
@ -64,6 +64,8 @@ pub use lower::{
|
|||
};
|
||||
pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
|
||||
|
||||
pub use chalk_ir::{BoundVar, DebruijnIndex};
|
||||
|
||||
/// A type constructor or type name: this might be something like the primitive
|
||||
/// type `bool`, a struct like `Vec`, or things like function pointers or
|
||||
/// tuples.
|
||||
|
@ -265,7 +267,11 @@ impl TypeWalk for ProjectionTy {
|
|||
self.parameters.walk(f);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.parameters.walk_mut_binders(f, binders);
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +305,7 @@ pub enum Ty {
|
|||
/// 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.
|
||||
Bound(u32),
|
||||
Bound(BoundVar),
|
||||
|
||||
/// A type variable used during type checking.
|
||||
Infer(InferTy),
|
||||
|
@ -337,7 +343,11 @@ impl TypeWalk for Substs {
|
|||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
for t in make_mut_slice(&mut self.0) {
|
||||
t.walk_mut_binders(f, binders);
|
||||
}
|
||||
|
@ -381,7 +391,13 @@ impl Substs {
|
|||
|
||||
/// Return Substs that replace each parameter by a bound variable.
|
||||
pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
|
||||
Substs(generic_params.iter().enumerate().map(|(idx, _)| Ty::Bound(idx as u32)).collect())
|
||||
Substs(
|
||||
generic_params
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, _)| Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn build_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
|
||||
|
@ -425,8 +441,8 @@ impl SubstsBuilder {
|
|||
self.param_count - self.vec.len()
|
||||
}
|
||||
|
||||
pub fn fill_with_bound_vars(self, starting_from: u32) -> Self {
|
||||
self.fill((starting_from..).map(Ty::Bound))
|
||||
pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
|
||||
self.fill((starting_from..).map(|idx| Ty::Bound(BoundVar::new(debruijn, idx))))
|
||||
}
|
||||
|
||||
pub fn fill_with_unknown(self) -> Self {
|
||||
|
@ -507,7 +523,11 @@ impl TypeWalk for TraitRef {
|
|||
self.substs.walk(f);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.substs.walk_mut_binders(f, binders);
|
||||
}
|
||||
}
|
||||
|
@ -558,7 +578,11 @@ impl TypeWalk for GenericPredicate {
|
|||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
match self {
|
||||
GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
|
||||
GenericPredicate::Projection(projection_pred) => {
|
||||
|
@ -616,7 +640,11 @@ impl TypeWalk for FnSig {
|
|||
}
|
||||
}
|
||||
|
||||
fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
|
||||
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);
|
||||
}
|
||||
|
@ -755,7 +783,7 @@ impl Ty {
|
|||
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), 0);
|
||||
self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST);
|
||||
}
|
||||
/// Walk the type, counting entered binders.
|
||||
///
|
||||
|
@ -767,9 +795,17 @@ pub trait TypeWalk {
|
|||
/// that. Currently, the only thing that introduces bound variables on our
|
||||
/// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound
|
||||
/// variable for the self type.
|
||||
fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize);
|
||||
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, usize) -> Ty, binders: usize) -> Self
|
||||
fn fold_binders(
|
||||
mut self,
|
||||
f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty,
|
||||
binders: DebruijnIndex,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -795,40 +831,43 @@ pub trait TypeWalk {
|
|||
}
|
||||
|
||||
/// Substitutes `Ty::Bound` vars with the given substitution.
|
||||
fn subst_bound_vars(mut self, substs: &Substs) -> Self
|
||||
fn subst_bound_vars(self, substs: &Substs) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
|
||||
}
|
||||
|
||||
/// Substitutes `Ty::Bound` vars with the given substitution.
|
||||
fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.walk_mut_binders(
|
||||
&mut |ty, binders| {
|
||||
if let &mut Ty::Bound(idx) = ty {
|
||||
if idx as usize >= binders && (idx as usize - binders) < substs.len() {
|
||||
*ty = substs.0[idx as usize - binders].clone();
|
||||
} else if idx as usize >= binders + substs.len() {
|
||||
// shift free binders
|
||||
*ty = Ty::Bound(idx - substs.len() as u32);
|
||||
if let &mut Ty::Bound(bound) = ty {
|
||||
if bound.debruijn >= binders {
|
||||
*ty = substs.0[bound.index].clone();
|
||||
}
|
||||
}
|
||||
},
|
||||
0,
|
||||
depth,
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
/// Shifts up `Ty::Bound` vars by `n`.
|
||||
fn shift_bound_vars(self, n: i32) -> Self
|
||||
// /// Shifts up debruijn indices of `Ty::Bound` vars by `n`.
|
||||
fn shift_bound_vars(self, n: DebruijnIndex) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.fold_binders(
|
||||
&mut |ty, binders| match ty {
|
||||
Ty::Bound(idx) if idx as usize >= binders => {
|
||||
assert!(idx as i32 >= -n);
|
||||
Ty::Bound((idx as i32 + n) as u32)
|
||||
Ty::Bound(bound) if bound.debruijn >= binders => {
|
||||
Ty::Bound(bound.shifted_in_from(n))
|
||||
}
|
||||
ty => ty,
|
||||
},
|
||||
0,
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -856,7 +895,11 @@ impl TypeWalk for Ty {
|
|||
f(self);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
match self {
|
||||
Ty::Apply(a_ty) => {
|
||||
a_ty.parameters.walk_mut_binders(f, binders);
|
||||
|
@ -866,7 +909,7 @@ impl TypeWalk for Ty {
|
|||
}
|
||||
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
||||
for p in make_mut_slice(predicates) {
|
||||
p.walk_mut_binders(f, binders + 1);
|
||||
p.walk_mut_binders(f, binders.shifted_in());
|
||||
}
|
||||
}
|
||||
Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
|
||||
|
|
|
@ -29,8 +29,8 @@ use crate::{
|
|||
all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice,
|
||||
variant_data,
|
||||
},
|
||||
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
|
||||
TraitEnvironment, TraitRef, Ty, TypeCtor,
|
||||
Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate,
|
||||
ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -131,7 +131,7 @@ impl Ty {
|
|||
Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig)
|
||||
}
|
||||
TypeRef::DynTrait(bounds) => {
|
||||
let self_ty = Ty::Bound(0);
|
||||
let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
|
||||
let predicates = bounds
|
||||
.iter()
|
||||
.flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
|
||||
|
@ -141,7 +141,7 @@ impl Ty {
|
|||
TypeRef::ImplTrait(bounds) => {
|
||||
match ctx.impl_trait_mode {
|
||||
ImplTraitLoweringMode::Opaque => {
|
||||
let self_ty = Ty::Bound(0);
|
||||
let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
|
||||
let predicates = bounds
|
||||
.iter()
|
||||
.flat_map(|b| {
|
||||
|
@ -177,12 +177,10 @@ impl Ty {
|
|||
} else {
|
||||
(0, 0, 0, 0)
|
||||
};
|
||||
Ty::Bound(
|
||||
idx as u32
|
||||
+ parent_params as u32
|
||||
+ self_params as u32
|
||||
+ list_params as u32,
|
||||
)
|
||||
Ty::Bound(BoundVar::new(
|
||||
DebruijnIndex::INNERMOST,
|
||||
idx as usize + parent_params + self_params + list_params,
|
||||
))
|
||||
}
|
||||
ImplTraitLoweringMode::Disallowed => {
|
||||
// FIXME: report error
|
||||
|
@ -249,7 +247,11 @@ impl Ty {
|
|||
let ty = match resolution {
|
||||
TypeNs::TraitId(trait_) => {
|
||||
// if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
|
||||
let self_ty = if remaining_segments.len() == 0 { Some(Ty::Bound(0)) } else { None };
|
||||
let self_ty = if remaining_segments.len() == 0 {
|
||||
Some(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let trait_ref =
|
||||
TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
|
||||
let ty = if remaining_segments.len() == 1 {
|
||||
|
@ -289,7 +291,7 @@ impl Ty {
|
|||
TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
|
||||
TypeParamLoweringMode::Variable => {
|
||||
let idx = generics.param_idx(param_id).expect("matching generics");
|
||||
Ty::Bound(idx)
|
||||
Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -558,7 +560,7 @@ impl GenericPredicate {
|
|||
TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
|
||||
TypeParamLoweringMode::Variable => {
|
||||
let idx = generics.param_idx(param_id).expect("matching generics");
|
||||
Ty::Bound(idx)
|
||||
Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ use crate::{
|
|||
db::HirDatabase,
|
||||
primitive::{FloatBitness, Uncertain},
|
||||
utils::all_super_traits,
|
||||
ApplicationTy, Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
|
||||
ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty,
|
||||
TypeCtor, TypeWalk,
|
||||
};
|
||||
|
||||
/// This is used as a key for indexing impls.
|
||||
|
@ -507,8 +508,9 @@ pub(crate) fn inherent_impl_substs(
|
|||
) -> Option<Substs> {
|
||||
// we create a var for each type parameter of the impl; we need to keep in
|
||||
// mind here that `self_ty` might have vars of its own
|
||||
let vars =
|
||||
Substs::build_for_def(db, impl_id).fill_with_bound_vars(self_ty.num_vars as u32).build();
|
||||
let vars = Substs::build_for_def(db, impl_id)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.num_vars)
|
||||
.build();
|
||||
let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
|
||||
let self_ty_with_vars =
|
||||
Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars };
|
||||
|
@ -526,8 +528,8 @@ pub(crate) fn inherent_impl_substs(
|
|||
fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
|
||||
s.fold_binders(
|
||||
&mut |ty, binders| {
|
||||
if let Ty::Bound(idx) = &ty {
|
||||
if *idx >= binders as u32 {
|
||||
if let Ty::Bound(bound) = &ty {
|
||||
if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
|
||||
Ty::Unknown
|
||||
} else {
|
||||
ty
|
||||
|
@ -536,7 +538,7 @@ fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
|
|||
ty
|
||||
}
|
||||
},
|
||||
num_vars_to_keep,
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -586,7 +588,7 @@ fn generic_implements_goal(
|
|||
let num_vars = self_ty.num_vars;
|
||||
let substs = super::Substs::build_for_def(db, trait_)
|
||||
.push(self_ty.value)
|
||||
.fill_with_bound_vars(num_vars as u32)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, num_vars)
|
||||
.build();
|
||||
let num_vars = substs.len() - 1 + self_ty.num_vars;
|
||||
let trait_ref = TraitRef { trait_, substs };
|
||||
|
|
|
@ -7,7 +7,7 @@ use ra_db::{impl_intern_key, salsa, CrateId};
|
|||
use ra_prof::profile;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use crate::db::HirDatabase;
|
||||
use crate::{db::HirDatabase, DebruijnIndex};
|
||||
|
||||
use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
|
||||
|
||||
|
@ -128,7 +128,11 @@ impl TypeWalk for ProjectionPredicate {
|
|||
self.ty.walk(f);
|
||||
}
|
||||
|
||||
fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
|
||||
fn walk_mut_binders(
|
||||
&mut self,
|
||||
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
|
||||
binders: DebruijnIndex,
|
||||
) {
|
||||
self.projection_ty.walk_mut_binders(f, binders);
|
||||
self.ty.walk_mut_binders(f, binders);
|
||||
}
|
||||
|
@ -144,7 +148,7 @@ pub(crate) fn trait_solve_query(
|
|||
Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(),
|
||||
Obligation::Projection(_) => "projection".to_string(),
|
||||
});
|
||||
log::debug!("trait_solve_query({})", goal.value.value.display(db));
|
||||
eprintln!("trait_solve_query({})", goal.value.value.display(db));
|
||||
|
||||
if let Obligation::Projection(pred) = &goal.value.value {
|
||||
if let Ty::Bound(_) = &pred.projection_ty.parameters[0] {
|
||||
|
|
|
@ -8,7 +8,8 @@ use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData};
|
|||
use crate::{
|
||||
db::HirDatabase,
|
||||
utils::{all_super_traits, generics},
|
||||
ApplicationTy, Binders, GenericPredicate, Substs, TraitRef, Ty, TypeCtor,
|
||||
ApplicationTy, Binders, BoundVar, DebruijnIndex, GenericPredicate, Substs, TraitRef, Ty,
|
||||
TypeCtor, TypeWalk,
|
||||
};
|
||||
|
||||
pub(super) struct BuiltinImplData {
|
||||
|
@ -164,11 +165,15 @@ fn closure_fn_trait_impl_datum(
|
|||
|
||||
let arg_ty = Ty::apply(
|
||||
TypeCtor::Tuple { cardinality: num_args },
|
||||
Substs::builder(num_args as usize).fill_with_bound_vars(0).build(),
|
||||
Substs::builder(num_args as usize)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
||||
.build(),
|
||||
);
|
||||
let sig_ty = Ty::apply(
|
||||
TypeCtor::FnPtr { num_args },
|
||||
Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(),
|
||||
Substs::builder(num_args as usize + 1)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
||||
.build(),
|
||||
);
|
||||
|
||||
let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
|
||||
|
@ -203,7 +208,7 @@ fn closure_fn_trait_output_assoc_ty_value(
|
|||
}
|
||||
};
|
||||
|
||||
let output_ty = Ty::Bound(num_args.into());
|
||||
let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into()));
|
||||
|
||||
let fn_once_trait =
|
||||
get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
|
||||
|
@ -241,7 +246,7 @@ fn array_unsize_impl_datum(db: &dyn HirDatabase, krate: CrateId) -> BuiltinImplD
|
|||
// the existence of the Unsize trait has been checked before
|
||||
.expect("Unsize trait missing");
|
||||
|
||||
let var = Ty::Bound(0);
|
||||
let var = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
|
||||
let substs = Substs::builder(2)
|
||||
.push(Ty::apply_one(TypeCtor::Array, var.clone()))
|
||||
.push(Ty::apply_one(TypeCtor::Slice, var))
|
||||
|
@ -270,19 +275,18 @@ fn trait_object_unsize_impl_datum(
|
|||
// the existence of the Unsize trait has been checked before
|
||||
.expect("Unsize trait missing");
|
||||
|
||||
let self_ty = Ty::Bound(0);
|
||||
let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
|
||||
|
||||
let target_substs = Substs::build_for_def(db, trait_)
|
||||
.push(Ty::Bound(0))
|
||||
// starting from ^2 because we want to start with ^1 outside of the
|
||||
// `dyn`, which is ^2 inside
|
||||
.fill_with_bound_vars(2)
|
||||
.push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
|
||||
.fill_with_bound_vars(DebruijnIndex::ONE, 1)
|
||||
.build();
|
||||
let num_vars = target_substs.len();
|
||||
let target_trait_ref = TraitRef { trait_, substs: target_substs };
|
||||
let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)];
|
||||
|
||||
let self_substs = Substs::build_for_def(db, trait_).fill_with_bound_vars(0).build();
|
||||
let self_substs =
|
||||
Substs::build_for_def(db, trait_).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
|
||||
let self_trait_ref = TraitRef { trait_, substs: self_substs };
|
||||
let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)];
|
||||
|
||||
|
@ -305,24 +309,26 @@ fn super_trait_object_unsize_impl_datum(
|
|||
// the existence of the Unsize trait has been checked before
|
||||
.expect("Unsize trait missing");
|
||||
|
||||
let self_substs = Substs::build_for_def(db, data.trait_).fill_with_bound_vars(0).build();
|
||||
let self_substs = Substs::build_for_def(db, data.trait_)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
||||
.build();
|
||||
let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() };
|
||||
|
||||
let num_vars = self_substs.len() - 1;
|
||||
|
||||
let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() };
|
||||
let self_bounds = vec![GenericPredicate::Implemented(self_trait_ref.clone())];
|
||||
|
||||
// we need to go from our trait to the super trait, substituting type parameters
|
||||
let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait);
|
||||
|
||||
let mut current_trait_ref = self_trait_ref;
|
||||
let mut current_trait_ref = self_trait_ref.clone();
|
||||
for t in path.into_iter().skip(1) {
|
||||
let bounds = db.generic_predicates(current_trait_ref.trait_.into());
|
||||
let super_trait_ref = bounds
|
||||
.iter()
|
||||
.find_map(|b| match &b.value {
|
||||
GenericPredicate::Implemented(tr)
|
||||
if tr.trait_ == t && tr.substs[0] == Ty::Bound(0) =>
|
||||
if tr.trait_ == t
|
||||
&& tr.substs[0]
|
||||
== Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)) =>
|
||||
{
|
||||
Some(Binders { value: tr, num_binders: b.num_binders })
|
||||
}
|
||||
|
@ -332,7 +338,18 @@ fn super_trait_object_unsize_impl_datum(
|
|||
current_trait_ref = super_trait_ref.cloned().subst(¤t_trait_ref.substs);
|
||||
}
|
||||
|
||||
let super_bounds = vec![GenericPredicate::Implemented(current_trait_ref)];
|
||||
// We need to renumber the variables a bit now: from ^0.0, ^0.1, ^0.2, ...
|
||||
// to ^0.0, ^1.0, ^1.1. The reason for this is that the first variable comes
|
||||
// from the dyn Trait binder, while the other variables come from the impl.
|
||||
let new_substs = Substs::builder(num_vars + 1)
|
||||
.push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
|
||||
.fill_with_bound_vars(DebruijnIndex::ONE, 0)
|
||||
.build();
|
||||
|
||||
let self_bounds =
|
||||
vec![GenericPredicate::Implemented(self_trait_ref.subst_bound_vars(&new_substs))];
|
||||
let super_bounds =
|
||||
vec![GenericPredicate::Implemented(current_trait_ref.subst_bound_vars(&new_substs))];
|
||||
|
||||
let substs = Substs::builder(2)
|
||||
.push(Ty::Dyn(self_bounds.into()))
|
||||
|
|
|
@ -3,7 +3,10 @@ use std::{fmt, sync::Arc};
|
|||
|
||||
use log::debug;
|
||||
|
||||
use chalk_ir::{cast::Cast, Goal, GoalData, Parameter, PlaceholderIndex, TypeName, UniverseIndex};
|
||||
use chalk_ir::{
|
||||
cast::Cast, fold::shift::Shift, Goal, GoalData, Parameter, PlaceholderIndex, TypeName,
|
||||
UniverseIndex,
|
||||
};
|
||||
|
||||
use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId};
|
||||
use ra_db::{
|
||||
|
@ -235,7 +238,7 @@ impl ToChalk for Ty {
|
|||
}
|
||||
.to_ty::<Interner>(&Interner)
|
||||
}
|
||||
Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(&Interner),
|
||||
Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner),
|
||||
Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
|
||||
Ty::Dyn(predicates) => {
|
||||
let where_clauses = predicates
|
||||
|
@ -277,7 +280,7 @@ impl ToChalk for Ty {
|
|||
Ty::Projection(ProjectionTy { associated_ty, parameters })
|
||||
}
|
||||
chalk_ir::TyData::Function(_) => unimplemented!(),
|
||||
chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32),
|
||||
chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx),
|
||||
chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown,
|
||||
chalk_ir::TyData::Dyn(where_clauses) => {
|
||||
assert_eq!(where_clauses.bounds.binders.len(), 1);
|
||||
|
@ -407,15 +410,15 @@ impl ToChalk for GenericPredicate {
|
|||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> {
|
||||
match self {
|
||||
GenericPredicate::Implemented(trait_ref) => {
|
||||
make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0)
|
||||
let chalk_trait_ref = trait_ref.to_chalk(db);
|
||||
let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner);
|
||||
make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0)
|
||||
}
|
||||
GenericPredicate::Projection(projection_pred) => {
|
||||
let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner);
|
||||
let alias = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner);
|
||||
make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0)
|
||||
}
|
||||
GenericPredicate::Projection(projection_pred) => make_binders(
|
||||
chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
|
||||
alias: projection_pred.projection_ty.to_chalk(db),
|
||||
ty: projection_pred.ty.to_chalk(db),
|
||||
}),
|
||||
0,
|
||||
),
|
||||
GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +582,8 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData {
|
|||
type Chalk = AssociatedTyValue;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue {
|
||||
let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) };
|
||||
let ty = self.value.to_chalk(db);
|
||||
let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty };
|
||||
|
||||
chalk_rust_ir::AssociatedTyValue {
|
||||
associated_ty_id: self.assoc_ty_id.to_chalk(db),
|
||||
|
@ -738,11 +742,13 @@ pub(crate) fn trait_datum_query(
|
|||
let associated_ty_ids =
|
||||
trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect();
|
||||
let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses };
|
||||
let well_known = None; // FIXME set this (depending on lang items)
|
||||
let trait_datum = TraitDatum {
|
||||
id: trait_id,
|
||||
binders: make_binders(trait_datum_bound, bound_vars.len()),
|
||||
flags,
|
||||
associated_ty_ids,
|
||||
well_known,
|
||||
};
|
||||
Arc::new(trait_datum)
|
||||
}
|
||||
|
|
|
@ -201,11 +201,11 @@ impl Generics {
|
|||
(parent, self_params, list_params, impl_trait_params)
|
||||
}
|
||||
|
||||
pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> {
|
||||
pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<usize> {
|
||||
Some(self.find_param(param)?.0)
|
||||
}
|
||||
|
||||
fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> {
|
||||
fn find_param(&self, param: TypeParamId) -> Option<(usize, &TypeParamData)> {
|
||||
if param.parent == self.def {
|
||||
let (idx, (_local_id, data)) = self
|
||||
.params
|
||||
|
@ -215,7 +215,7 @@ impl Generics {
|
|||
.find(|(_, (idx, _))| *idx == param.local_id)
|
||||
.unwrap();
|
||||
let (_total, parent_len, _child) = self.len_split();
|
||||
Some(((parent_len + idx) as u32, data))
|
||||
Some((parent_len + idx, data))
|
||||
} else {
|
||||
self.parent_generics.as_ref().and_then(|g| g.find_param(param))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue