aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/autoderef.rs51
-rw-r--r--crates/hir_ty/src/infer.rs2
-rw-r--r--crates/hir_ty/src/infer/coerce.rs6
-rw-r--r--crates/hir_ty/src/infer/expr.rs16
-rw-r--r--crates/hir_ty/src/infer/unify.rs51
-rw-r--r--crates/hir_ty/src/lib.rs12
-rw-r--r--crates/hir_ty/src/method_resolution.rs53
-rw-r--r--crates/hir_ty/src/traits.rs17
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs32
9 files changed, 131 insertions, 109 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 23ab042c1..dc5fc759a 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -16,8 +16,8 @@ use crate::{
16 to_assoc_type_id, to_chalk_trait_id, 16 to_assoc_type_id, to_chalk_trait_id,
17 traits::{InEnvironment, Solution}, 17 traits::{InEnvironment, Solution},
18 utils::generics, 18 utils::generics,
19 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution, 19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
20 TraitRef, Ty, TyKind, 20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 21};
22 22
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 23const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -27,9 +27,9 @@ pub fn autoderef<'a>(
27 krate: Option<CrateId>, 27 krate: Option<CrateId>,
28 ty: InEnvironment<Canonical<Ty>>, 28 ty: InEnvironment<Canonical<Ty>>,
29) -> impl Iterator<Item = Canonical<Ty>> + 'a { 29) -> impl Iterator<Item = Canonical<Ty>> + 'a {
30 let InEnvironment { value: ty, environment } = ty; 30 let InEnvironment { goal: ty, environment } = ty;
31 successors(Some(ty), move |ty| { 31 successors(Some(ty), move |ty| {
32 deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) 32 deref(db, krate?, InEnvironment { goal: ty, environment: environment.clone() })
33 }) 33 })
34 .take(AUTODEREF_RECURSION_LIMIT) 34 .take(AUTODEREF_RECURSION_LIMIT)
35} 35}
@@ -39,8 +39,8 @@ pub(crate) fn deref(
39 krate: CrateId, 39 krate: CrateId,
40 ty: InEnvironment<&Canonical<Ty>>, 40 ty: InEnvironment<&Canonical<Ty>>,
41) -> Option<Canonical<Ty>> { 41) -> Option<Canonical<Ty>> {
42 if let Some(derefed) = ty.value.value.builtin_deref() { 42 if let Some(derefed) = ty.goal.value.builtin_deref() {
43 Some(Canonical { value: derefed, kinds: ty.value.kinds.clone() }) 43 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
44 } else { 44 } else {
45 deref_by_trait(db, krate, ty) 45 deref_by_trait(db, krate, ty)
46 } 46 }
@@ -67,15 +67,15 @@ fn deref_by_trait(
67 // FIXME make the Canonical / bound var handling nicer 67 // FIXME make the Canonical / bound var handling nicer
68 68
69 let parameters = 69 let parameters =
70 Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build(); 70 Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build();
71 71
72 // Check that the type implements Deref at all 72 // Check that the type implements Deref at all
73 let trait_ref = 73 let trait_ref =
74 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; 74 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
75 let implements_goal = Canonical { 75 let implements_goal = Canonical {
76 kinds: ty.value.kinds.clone(), 76 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 77 value: InEnvironment {
78 value: trait_ref.cast(&Interner), 78 goal: trait_ref.cast(&Interner),
79 environment: ty.environment.clone(), 79 environment: ty.environment.clone(),
80 }, 80 },
81 }; 81 };
@@ -89,18 +89,27 @@ fn deref_by_trait(
89 associated_ty_id: to_assoc_type_id(target), 89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters, 90 substitution: parameters,
91 }), 91 }),
92 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) 92 ty: TyKind::BoundVar(BoundVar::new(
93 .intern(&Interner), 93 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner),
95 ))
96 .intern(&Interner),
94 }; 97 };
95 98
96 let obligation = projection.cast(&Interner); 99 let obligation = projection.cast(&Interner);
97 100
98 let in_env = InEnvironment { value: obligation, environment: ty.environment }; 101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
99 102
100 let canonical = Canonical::new( 103 let canonical = Canonical {
101 in_env, 104 value: in_env,
102 ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)), 105 binders: CanonicalVarKinds::from_iter(
103 ); 106 &Interner,
107 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
108 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
109 chalk_ir::UniverseIndex::ROOT,
110 ))),
111 ),
112 };
104 113
105 let solution = db.trait_solve(krate, canonical)?; 114 let solution = db.trait_solve(krate, canonical)?;
106 115
@@ -121,21 +130,21 @@ fn deref_by_trait(
121 // assumptions will be broken. We would need to properly introduce 130 // assumptions will be broken. We would need to properly introduce
122 // new variables in that case 131 // new variables in that case
123 132
124 for i in 1..vars.0.kinds.len() { 133 for i in 1..vars.0.binders.len(&Interner) {
125 if vars.0.value[i - 1].interned(&Interner) 134 if vars.0.value[i - 1].interned(&Interner)
126 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 135 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
127 { 136 {
128 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); 137 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
129 return None; 138 return None;
130 } 139 }
131 } 140 }
132 Some(Canonical { 141 Some(Canonical {
133 value: vars.0.value[vars.0.value.len() - 1].clone(), 142 value: vars.0.value[vars.0.value.len() - 1].clone(),
134 kinds: vars.0.kinds.clone(), 143 binders: vars.0.binders.clone(),
135 }) 144 })
136 } 145 }
137 Solution::Ambig(_) => { 146 Solution::Ambig(_) => {
138 info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); 147 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
139 None 148 None
140 } 149 }
141 } 150 }
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index b9e434c78..8f9cf7480 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -331,7 +331,7 @@ impl<'a> InferenceContext<'a> {
331 fn resolve_obligations_as_possible(&mut self) { 331 fn resolve_obligations_as_possible(&mut self) {
332 let obligations = mem::replace(&mut self.obligations, Vec::new()); 332 let obligations = mem::replace(&mut self.obligations, Vec::new());
333 for obligation in obligations { 333 for obligation in obligations {
334 let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone()); 334 let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone());
335 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); 335 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
336 let solution = 336 let solution =
337 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 337 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 07eb96573..9c62932b1 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -142,7 +142,7 @@ impl<'a> InferenceContext<'a> {
142 .build(); 142 .build();
143 let trait_ref = 143 let trait_ref =
144 TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; 144 TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
145 let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner)); 145 let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner));
146 146
147 let canonicalizer = self.canonicalizer(); 147 let canonicalizer = self.canonicalizer();
148 let canonicalized = canonicalizer.canonicalize_obligation(goal); 148 let canonicalized = canonicalizer.canonicalize_obligation(goal);
@@ -170,8 +170,8 @@ impl<'a> InferenceContext<'a> {
170 self.db, 170 self.db,
171 self.resolver.krate(), 171 self.resolver.krate(),
172 InEnvironment { 172 InEnvironment {
173 value: canonicalized.value.clone(), 173 goal: canonicalized.value.clone(),
174 environment: self.trait_env.clone(), 174 environment: self.trait_env.env.clone(),
175 }, 175 },
176 ) { 176 ) {
177 let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); 177 let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value);
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 05cbde4e3..19249973c 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -90,12 +90,12 @@ impl<'a> InferenceContext<'a> {
90 let substs = 90 let substs =
91 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); 91 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
92 92
93 let trait_env = Arc::clone(&self.trait_env); 93 let trait_env = self.trait_env.env.clone();
94 let implements_fn_trait: DomainGoal = 94 let implements_fn_trait: DomainGoal =
95 TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } 95 TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() }
96 .cast(&Interner); 96 .cast(&Interner);
97 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { 97 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
98 value: implements_fn_trait.clone(), 98 goal: implements_fn_trait.clone(),
99 environment: trait_env, 99 environment: trait_env,
100 }); 100 });
101 if self.db.trait_solve(krate, goal.value).is_some() { 101 if self.db.trait_solve(krate, goal.value).is_some() {
@@ -299,8 +299,8 @@ impl<'a> InferenceContext<'a> {
299 self.db, 299 self.db,
300 self.resolver.krate(), 300 self.resolver.krate(),
301 InEnvironment { 301 InEnvironment {
302 value: canonicalized.value.clone(), 302 goal: canonicalized.value.clone(),
303 environment: self.trait_env.clone(), 303 environment: self.trait_env.env.clone(),
304 }, 304 },
305 ); 305 );
306 let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs 306 let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs
@@ -438,8 +438,8 @@ impl<'a> InferenceContext<'a> {
438 self.db, 438 self.db,
439 self.resolver.krate(), 439 self.resolver.krate(),
440 InEnvironment { 440 InEnvironment {
441 value: canonicalized.value.clone(), 441 goal: canonicalized.value.clone(),
442 environment: self.trait_env.clone(), 442 environment: self.trait_env.env.clone(),
443 }, 443 },
444 ) 444 )
445 .find_map(|derefed_ty| { 445 .find_map(|derefed_ty| {
@@ -538,8 +538,8 @@ impl<'a> InferenceContext<'a> {
538 self.db, 538 self.db,
539 krate, 539 krate,
540 InEnvironment { 540 InEnvironment {
541 value: &canonicalized.value, 541 goal: &canonicalized.value,
542 environment: self.trait_env.clone(), 542 environment: self.trait_env.env.clone(),
543 }, 543 },
544 ) { 544 ) {
545 Some(derefed_ty) => { 545 Some(derefed_ty) => {
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 35b0a2059..75250a369 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -2,13 +2,13 @@
2 2
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind}; 5use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{DomainGoal, InferenceContext}; 8use super::{DomainGoal, InferenceContext};
9use crate::{ 9use crate::{
10 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar, 10 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer,
11 Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, 11 InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
12}; 12};
13 13
14impl<'a> InferenceContext<'a> { 14impl<'a> InferenceContext<'a> {
@@ -76,8 +76,17 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
76 } 76 }
77 77
78 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 78 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
79 let kinds = self.free_vars.iter().map(|&(_, k)| k).collect(); 79 let kinds = self
80 Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } 80 .free_vars
81 .iter()
82 .map(|&(_, k)| chalk_ir::WithKind::new(VariableKind::Ty(k), UniverseIndex::ROOT));
83 Canonicalized {
84 value: Canonical {
85 value: result,
86 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
87 },
88 free_vars: self.free_vars,
89 }
81 } 90 }
82 91
83 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { 92 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
@@ -89,15 +98,12 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
89 mut self, 98 mut self,
90 obligation: InEnvironment<DomainGoal>, 99 obligation: InEnvironment<DomainGoal>,
91 ) -> Canonicalized<InEnvironment<DomainGoal>> { 100 ) -> Canonicalized<InEnvironment<DomainGoal>> {
92 let result = match obligation.value { 101 let result = match obligation.goal {
93 DomainGoal::Holds(wc) => { 102 DomainGoal::Holds(wc) => {
94 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) 103 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
95 } 104 }
96 }; 105 };
97 self.into_canonicalized(InEnvironment { 106 self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment })
98 value: result,
99 environment: obligation.environment,
100 })
101 } 107 }
102} 108}
103 109
@@ -125,12 +131,19 @@ impl<T> Canonicalized<T> {
125 // the solution may contain new variables, which we need to convert to new inference vars 131 // the solution may contain new variables, which we need to convert to new inference vars
126 let new_vars = Substitution( 132 let new_vars = Substitution(
127 solution 133 solution
128 .kinds 134 .binders
129 .iter() 135 .iter(&Interner)
130 .map(|k| match k { 136 .map(|k| match k.kind {
131 TyVariableKind::General => ctx.table.new_type_var(), 137 VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(),
132 TyVariableKind::Integer => ctx.table.new_integer_var(), 138 VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(),
133 TyVariableKind::Float => ctx.table.new_float_var(), 139 VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(),
140 // HACK: Chalk can sometimes return new lifetime variables. We
141 // want to just skip them, but to not mess up the indices of
142 // other variables, we'll just create a new type variable in
143 // their place instead. This should not matter (we never see the
144 // actual *uses* of the lifetime variable).
145 VariableKind::Lifetime => ctx.table.new_type_var(),
146 _ => panic!("const variable in solution"),
134 }) 147 })
135 .collect(), 148 .collect(),
136 ); 149 );
@@ -147,8 +160,8 @@ impl<T> Canonicalized<T> {
147pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { 160pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> {
148 let mut table = InferenceTable::new(); 161 let mut table = InferenceTable::new();
149 let vars = Substitution( 162 let vars = Substitution(
150 tys.kinds 163 tys.binders
151 .iter() 164 .iter(&Interner)
152 // we always use type vars here because we want everything to 165 // we always use type vars here because we want everything to
153 // fallback to Unknown in the end (kind of hacky, as below) 166 // fallback to Unknown in the end (kind of hacky, as below)
154 .map(|_| table.new_type_var()) 167 .map(|_| table.new_type_var())
@@ -170,7 +183,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> {
170 } 183 }
171 } 184 }
172 Some( 185 Some(
173 Substitution::builder(tys.kinds.len()) 186 Substitution::builder(tys.binders.len(&Interner))
174 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) 187 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
175 .build(), 188 .build(),
176 ) 189 )
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 90b5b17e2..0f49dd39b 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -61,6 +61,8 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>;
61pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 61pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
62pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; 62pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
63 63
64pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
65
64pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 66pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
65 67
66#[derive(Clone, PartialEq, Eq, Debug, Hash)] 68#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -662,12 +664,18 @@ impl QuantifiedWhereClauses {
662#[derive(Debug, Clone, PartialEq, Eq, Hash)] 664#[derive(Debug, Clone, PartialEq, Eq, Hash)]
663pub struct Canonical<T> { 665pub struct Canonical<T> {
664 pub value: T, 666 pub value: T,
665 pub kinds: Arc<[TyVariableKind]>, 667 pub binders: CanonicalVarKinds,
666} 668}
667 669
668impl<T> Canonical<T> { 670impl<T> Canonical<T> {
669 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { 671 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self {
670 Self { value, kinds: kinds.into_iter().collect() } 672 let kinds = kinds.into_iter().map(|tk| {
673 chalk_ir::CanonicalVarKind::new(
674 chalk_ir::VariableKind::Ty(tk),
675 chalk_ir::UniverseIndex::ROOT,
676 )
677 });
678 Self { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
671 } 679 }
672} 680}
673 681
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index da6bc2a4a..8e986ddde 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -6,7 +6,7 @@ use std::{iter, sync::Arc};
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::{cast::Cast, Mutability}; 9use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
10use hir_def::{ 10use hir_def::{
11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, 11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
12 ImplId, Lookup, ModuleId, TraitId, 12 ImplId, Lookup, ModuleId, TraitId,
@@ -21,8 +21,9 @@ use crate::{
21 primitive::{self, FloatTy, IntTy, UintTy}, 21 primitive::{self, FloatTy, IntTy, UintTy},
22 to_chalk_trait_id, 22 to_chalk_trait_id,
23 utils::all_super_traits, 23 utils::all_super_traits,
24 AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner, 24 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId,
25 Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, 25 InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind,
26 TypeWalk,
26}; 27};
27 28
28/// This is used as a key for indexing impls. 29/// This is used as a key for indexing impls.
@@ -375,7 +376,7 @@ fn iterate_method_candidates_impl(
375 // Also note that when we've got a receiver like &S, even if the method we 376 // Also note that when we've got a receiver like &S, even if the method we
376 // find in the end takes &self, we still do the autoderef step (just as 377 // find in the end takes &self, we still do the autoderef step (just as
377 // rustc does an autoderef and then autoref again). 378 // rustc does an autoderef and then autoref again).
378 let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; 379 let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() };
379 380
380 // We have to be careful about the order we're looking at candidates 381 // We have to be careful about the order we're looking at candidates
381 // in here. Consider the case where we're resolving `x.clone()` 382 // in here. Consider the case where we're resolving `x.clone()`
@@ -443,7 +444,7 @@ fn iterate_method_candidates_with_autoref(
443 return true; 444 return true;
444 } 445 }
445 let refed = Canonical { 446 let refed = Canonical {
446 kinds: deref_chain[0].kinds.clone(), 447 binders: deref_chain[0].binders.clone(),
447 value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), 448 value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner),
448 }; 449 };
449 if iterate_method_candidates_by_receiver( 450 if iterate_method_candidates_by_receiver(
@@ -459,7 +460,7 @@ fn iterate_method_candidates_with_autoref(
459 return true; 460 return true;
460 } 461 }
461 let ref_muted = Canonical { 462 let ref_muted = Canonical {
462 kinds: deref_chain[0].kinds.clone(), 463 binders: deref_chain[0].binders.clone(),
463 value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), 464 value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner),
464 }; 465 };
465 if iterate_method_candidates_by_receiver( 466 if iterate_method_candidates_by_receiver(
@@ -621,7 +622,7 @@ pub fn resolve_indexing_op(
621 krate: CrateId, 622 krate: CrateId,
622 index_trait: TraitId, 623 index_trait: TraitId,
623) -> Option<Canonical<Ty>> { 624) -> Option<Canonical<Ty>> {
624 let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; 625 let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() };
625 let deref_chain = autoderef_method_receiver(db, krate, ty); 626 let deref_chain = autoderef_method_receiver(db, krate, ty);
626 for ty in deref_chain { 627 for ty in deref_chain {
627 let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); 628 let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone());
@@ -677,19 +678,28 @@ pub(crate) fn inherent_impl_substs(
677 // we create a var for each type parameter of the impl; we need to keep in 678 // we create a var for each type parameter of the impl; we need to keep in
678 // mind here that `self_ty` might have vars of its own 679 // mind here that `self_ty` might have vars of its own
679 let vars = Substitution::build_for_def(db, impl_id) 680 let vars = Substitution::build_for_def(db, impl_id)
680 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.kinds.len()) 681 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner))
681 .build(); 682 .build();
682 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 683 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
683 let mut kinds = self_ty.kinds.to_vec(); 684 let mut kinds = self_ty.binders.interned().to_vec();
684 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(vars.len())); 685 kinds.extend(
685 let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) }; 686 iter::repeat(chalk_ir::WithKind::new(
687 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
688 UniverseIndex::ROOT,
689 ))
690 .take(vars.len()),
691 );
692 let tys = Canonical {
693 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
694 value: (self_ty_with_vars, self_ty.value.clone()),
695 };
686 let substs = super::infer::unify(&tys); 696 let substs = super::infer::unify(&tys);
687 // We only want the substs for the vars we added, not the ones from self_ty. 697 // We only want the substs for the vars we added, not the ones from self_ty.
688 // Also, if any of the vars we added are still in there, we replace them by 698 // Also, if any of the vars we added are still in there, we replace them by
689 // Unknown. I think this can only really happen if self_ty contained 699 // Unknown. I think this can only really happen if self_ty contained
690 // Unknown, and in that case we want the result to contain Unknown in those 700 // Unknown, and in that case we want the result to contain Unknown in those
691 // places again. 701 // places again.
692 substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.kinds.len())) 702 substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.binders.len(&Interner)))
693} 703}
694 704
695/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 705/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
@@ -768,15 +778,24 @@ fn generic_implements_goal(
768 trait_: TraitId, 778 trait_: TraitId,
769 self_ty: Canonical<Ty>, 779 self_ty: Canonical<Ty>,
770) -> Canonical<InEnvironment<super::DomainGoal>> { 780) -> Canonical<InEnvironment<super::DomainGoal>> {
771 let mut kinds = self_ty.kinds.to_vec(); 781 let mut kinds = self_ty.binders.interned().to_vec();
772 let substs = super::Substitution::build_for_def(db, trait_) 782 let substs = super::Substitution::build_for_def(db, trait_)
773 .push(self_ty.value) 783 .push(self_ty.value)
774 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) 784 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
775 .build(); 785 .build();
776 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); 786 kinds.extend(
787 iter::repeat(chalk_ir::WithKind::new(
788 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
789 UniverseIndex::ROOT,
790 ))
791 .take(substs.len() - 1),
792 );
777 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; 793 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
778 let obligation = trait_ref.cast(&Interner); 794 let obligation = trait_ref.cast(&Interner);
779 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } 795 Canonical {
796 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
797 value: InEnvironment::new(env.env.clone(), obligation),
798 }
780} 799}
781 800
782fn autoderef_method_receiver( 801fn autoderef_method_receiver(
@@ -789,9 +808,9 @@ fn autoderef_method_receiver(
789 if let Some(TyKind::Array(parameters)) = 808 if let Some(TyKind::Array(parameters)) =
790 deref_chain.last().map(|ty| ty.value.interned(&Interner)) 809 deref_chain.last().map(|ty| ty.value.interned(&Interner))
791 { 810 {
792 let kinds = deref_chain.last().unwrap().kinds.clone(); 811 let kinds = deref_chain.last().unwrap().binders.clone();
793 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); 812 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
794 deref_chain.push(Canonical { value: unsized_ty, kinds }) 813 deref_chain.push(Canonical { value: unsized_ty, binders: kinds })
795 } 814 }
796 deref_chain 815 deref_chain
797} 816}
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index 7dadd1ffb..ccee0e5ad 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -1,6 +1,5 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2use std::env::var; 2use std::env::var;
3use std::sync::Arc;
4 3
5use base_db::CrateId; 4use base_db::CrateId;
6use chalk_ir::cast::Cast; 5use chalk_ir::cast::Cast;
@@ -44,7 +43,7 @@ pub struct TraitEnvironment {
44 // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, 43 // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord,
45 // but for now it's too annoying... 44 // but for now it's too annoying...
46 pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, 45 pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>,
47 pub(crate) env: chalk_ir::Environment<Interner>, 46 pub env: chalk_ir::Environment<Interner>,
48} 47}
49 48
50impl TraitEnvironment { 49impl TraitEnvironment {
@@ -74,13 +73,13 @@ impl Default for TraitEnvironment {
74/// Something (usually a goal), along with an environment. 73/// Something (usually a goal), along with an environment.
75#[derive(Clone, Debug, PartialEq, Eq, Hash)] 74#[derive(Clone, Debug, PartialEq, Eq, Hash)]
76pub struct InEnvironment<T> { 75pub struct InEnvironment<T> {
77 pub environment: Arc<TraitEnvironment>, 76 pub environment: chalk_ir::Environment<Interner>,
78 pub value: T, 77 pub goal: T,
79} 78}
80 79
81impl<T> InEnvironment<T> { 80impl<T> InEnvironment<T> {
82 pub fn new(environment: Arc<TraitEnvironment>, value: T) -> InEnvironment<T> { 81 pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> {
83 InEnvironment { environment, value } 82 InEnvironment { environment, goal: value }
84 } 83 }
85} 84}
86 85
@@ -126,18 +125,18 @@ pub(crate) fn trait_solve_query(
126 krate: CrateId, 125 krate: CrateId,
127 goal: Canonical<InEnvironment<DomainGoal>>, 126 goal: Canonical<InEnvironment<DomainGoal>>,
128) -> Option<Solution> { 127) -> Option<Solution> {
129 let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { 128 let _p = profile::span("trait_solve_query").detail(|| match &goal.value.goal {
130 DomainGoal::Holds(WhereClause::Implemented(it)) => { 129 DomainGoal::Holds(WhereClause::Implemented(it)) => {
131 db.trait_data(it.hir_trait_id()).name.to_string() 130 db.trait_data(it.hir_trait_id()).name.to_string()
132 } 131 }
133 DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), 132 DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
134 }); 133 });
135 log::info!("trait_solve_query({})", goal.value.value.display(db)); 134 log::info!("trait_solve_query({})", goal.value.goal.display(db));
136 135
137 if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq { 136 if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
138 alias: AliasTy::Projection(projection_ty), 137 alias: AliasTy::Projection(projection_ty),
139 .. 138 ..
140 })) = &goal.value.value 139 })) = &goal.value.goal
141 { 140 {
142 if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { 141 if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) {
143 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible 142 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 7209dd14e..aef6b8a15 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -439,35 +439,12 @@ where
439 type Chalk = chalk_ir::Canonical<T::Chalk>; 439 type Chalk = chalk_ir::Canonical<T::Chalk>;
440 440
441 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { 441 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
442 let kinds = self.kinds.iter().map(|&tk| {
443 chalk_ir::CanonicalVarKind::new(
444 chalk_ir::VariableKind::Ty(tk),
445 chalk_ir::UniverseIndex::ROOT,
446 )
447 });
448 let value = self.value.to_chalk(db); 442 let value = self.value.to_chalk(db);
449 chalk_ir::Canonical { 443 chalk_ir::Canonical { value, binders: self.binders }
450 value,
451 binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds),
452 }
453 } 444 }
454 445
455 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { 446 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
456 let kinds = canonical 447 Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) }
457 .binders
458 .iter(&Interner)
459 .map(|k| match k.kind {
460 chalk_ir::VariableKind::Ty(tk) => tk,
461 // HACK: Chalk can sometimes return new lifetime variables. We
462 // want to just skip them, but to not mess up the indices of
463 // other variables, we'll just create a new type variable in
464 // their place instead. This should not matter (we never see the
465 // actual *uses* of the lifetime variable).
466 chalk_ir::VariableKind::Lifetime => chalk_ir::TyVariableKind::General,
467 chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
468 })
469 .collect();
470 Canonical { kinds, value: from_chalk(db, canonical.value) }
471 } 448 }
472} 449}
473 450
@@ -478,10 +455,7 @@ where
478 type Chalk = chalk_ir::InEnvironment<T::Chalk>; 455 type Chalk = chalk_ir::InEnvironment<T::Chalk>;
479 456
480 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { 457 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
481 chalk_ir::InEnvironment { 458 chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) }
482 environment: self.environment.env.clone(),
483 goal: self.value.to_chalk(db),
484 }
485 } 459 }
486 460
487 fn from_chalk( 461 fn from_chalk(