aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yaml6
-rw-r--r--crates/ra_hir/src/code_model.rs10
-rw-r--r--crates/ra_hir_ty/src/autoderef.rs15
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs55
-rw-r--r--crates/ra_hir_ty/src/lib.rs22
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs32
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs18
-rw-r--r--crates/ra_hir_ty/src/traits.rs16
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs43
9 files changed, 143 insertions, 74 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ed9191c49..7f4e75341 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -116,9 +116,9 @@ jobs:
116 - run: npm ci 116 - run: npm ci
117 working-directory: ./editors/code 117 working-directory: ./editors/code
118 118
119 - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; } 119# - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; }
120 if: runner.os == 'Linux' 120# if: runner.os == 'Linux'
121 working-directory: ./editors/code 121# working-directory: ./editors/code
122 122
123 - run: npm run lint 123 - run: npm run lint
124 working-directory: ./editors/code 124 working-directory: ./editors/code
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index cc72964ff..1b3525011 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1189,7 +1189,7 @@ impl Type {
1189 None => return false, 1189 None => return false,
1190 }; 1190 };
1191 1191
1192 let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 }; 1192 let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
1193 method_resolution::implements_trait( 1193 method_resolution::implements_trait(
1194 &canonical_ty, 1194 &canonical_ty,
1195 db, 1195 db,
@@ -1213,7 +1213,7 @@ impl Type {
1213 self.ty.environment.clone(), 1213 self.ty.environment.clone(),
1214 hir_ty::Obligation::Trait(trait_ref), 1214 hir_ty::Obligation::Trait(trait_ref),
1215 ), 1215 ),
1216 num_vars: 0, 1216 kinds: Arc::new([]),
1217 }; 1217 };
1218 1218
1219 db.trait_solve(self.krate, goal).is_some() 1219 db.trait_solve(self.krate, goal).is_some()
@@ -1288,7 +1288,7 @@ impl Type {
1288 pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { 1288 pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
1289 // There should be no inference vars in types passed here 1289 // There should be no inference vars in types passed here
1290 // FIXME check that? 1290 // FIXME check that?
1291 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; 1291 let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
1292 let environment = self.ty.environment.clone(); 1292 let environment = self.ty.environment.clone();
1293 let ty = InEnvironment { value: canonical, environment }; 1293 let ty = InEnvironment { value: canonical, environment };
1294 autoderef(db, Some(self.krate), ty) 1294 autoderef(db, Some(self.krate), ty)
@@ -1329,7 +1329,7 @@ impl Type {
1329 // There should be no inference vars in types passed here 1329 // There should be no inference vars in types passed here
1330 // FIXME check that? 1330 // FIXME check that?
1331 // FIXME replace Unknown by bound vars here 1331 // FIXME replace Unknown by bound vars here
1332 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; 1332 let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
1333 1333
1334 let env = self.ty.environment.clone(); 1334 let env = self.ty.environment.clone();
1335 let krate = krate.id; 1335 let krate = krate.id;
@@ -1360,7 +1360,7 @@ impl Type {
1360 // There should be no inference vars in types passed here 1360 // There should be no inference vars in types passed here
1361 // FIXME check that? 1361 // FIXME check that?
1362 // FIXME replace Unknown by bound vars here 1362 // FIXME replace Unknown by bound vars here
1363 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; 1363 let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
1364 1364
1365 let env = self.ty.environment.clone(); 1365 let env = self.ty.environment.clone();
1366 let krate = krate.id; 1366 let krate = krate.id;
diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs
index 1b0f84c5c..c727012c6 100644
--- a/crates/ra_hir_ty/src/autoderef.rs
+++ b/crates/ra_hir_ty/src/autoderef.rs
@@ -37,7 +37,7 @@ pub(crate) fn deref(
37 ty: InEnvironment<&Canonical<Ty>>, 37 ty: InEnvironment<&Canonical<Ty>>,
38) -> Option<Canonical<Ty>> { 38) -> Option<Canonical<Ty>> {
39 if let Some(derefed) = ty.value.value.builtin_deref() { 39 if let Some(derefed) = ty.value.value.builtin_deref() {
40 Some(Canonical { value: derefed, num_vars: ty.value.num_vars }) 40 Some(Canonical { value: derefed, kinds: ty.value.kinds.clone() })
41 } else { 41 } else {
42 deref_by_trait(db, krate, ty) 42 deref_by_trait(db, krate, ty)
43 } 43 }
@@ -68,8 +68,8 @@ fn deref_by_trait(
68 68
69 // Check that the type implements Deref at all 69 // Check that the type implements Deref at all
70 let trait_ref = TraitRef { trait_: deref_trait, substs: parameters.clone() }; 70 let trait_ref = TraitRef { trait_: deref_trait, substs: parameters.clone() };
71 let implements_goal = super::Canonical { 71 let implements_goal = Canonical {
72 num_vars: ty.value.num_vars, 72 kinds: ty.value.kinds.clone(),
73 value: InEnvironment { 73 value: InEnvironment {
74 value: Obligation::Trait(trait_ref), 74 value: Obligation::Trait(trait_ref),
75 environment: ty.environment.clone(), 75 environment: ty.environment.clone(),
@@ -81,7 +81,7 @@ fn deref_by_trait(
81 81
82 // Now do the assoc type projection 82 // Now do the assoc type projection
83 let projection = super::traits::ProjectionPredicate { 83 let projection = super::traits::ProjectionPredicate {
84 ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.num_vars)), 84 ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())),
85 projection_ty: super::ProjectionTy { associated_ty: target, parameters }, 85 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
86 }; 86 };
87 87
@@ -89,7 +89,8 @@ fn deref_by_trait(
89 89
90 let in_env = InEnvironment { value: obligation, environment: ty.environment }; 90 let in_env = InEnvironment { value: obligation, environment: ty.environment };
91 91
92 let canonical = super::Canonical { num_vars: 1 + ty.value.num_vars, value: in_env }; 92 let canonical =
93 Canonical::new(in_env, ty.value.kinds.iter().copied().chain(Some(super::TyKind::General)));
93 94
94 let solution = db.trait_solve(krate, canonical)?; 95 let solution = db.trait_solve(krate, canonical)?;
95 96
@@ -110,7 +111,7 @@ fn deref_by_trait(
110 // assumptions will be broken. We would need to properly introduce 111 // assumptions will be broken. We would need to properly introduce
111 // new variables in that case 112 // new variables in that case
112 113
113 for i in 1..vars.0.num_vars { 114 for i in 1..vars.0.kinds.len() {
114 if vars.0.value[i - 1] != Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 115 if vars.0.value[i - 1] != Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
115 { 116 {
116 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); 117 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
@@ -119,7 +120,7 @@ fn deref_by_trait(
119 } 120 }
120 Some(Canonical { 121 Some(Canonical {
121 value: vars.0.value[vars.0.value.len() - 1].clone(), 122 value: vars.0.value[vars.0.value.len() - 1].clone(),
122 num_vars: vars.0.num_vars, 123 kinds: vars.0.kinds.clone(),
123 }) 124 })
124 } 125 }
125 Solution::Ambig(_) => { 126 Solution::Ambig(_) => {
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index 269495ca0..2e895d911 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -9,7 +9,7 @@ use test_utils::mark;
9use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
10use crate::{ 10use crate::{
11 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty, 11 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty,
12 TypeCtor, TypeWalk, 12 TyKind, TypeCtor, TypeWalk,
13}; 13};
14 14
15impl<'a> InferenceContext<'a> { 15impl<'a> InferenceContext<'a> {
@@ -86,10 +86,20 @@ where
86 } 86 }
87 87
88 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 88 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
89 Canonicalized { 89 let kinds = self
90 value: Canonical { value: result, num_vars: self.free_vars.len() }, 90 .free_vars
91 free_vars: self.free_vars, 91 .iter()
92 } 92 .map(|v| match v {
93 // mapping MaybeNeverTypeVar to the same kind as general ones
94 // should be fine, because as opposed to int or float type vars,
95 // they don't restrict what kind of type can go into them, they
96 // just affect fallback.
97 InferTy::TypeVar(_) | InferTy::MaybeNeverTypeVar(_) => TyKind::General,
98 InferTy::IntVar(_) => TyKind::Integer,
99 InferTy::FloatVar(_) => TyKind::Float,
100 })
101 .collect();
102 Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars }
93 } 103 }
94 104
95 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { 105 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
@@ -131,26 +141,41 @@ impl<T> Canonicalized<T> {
131 ty 141 ty
132 } 142 }
133 143
134 pub fn apply_solution(&self, ctx: &mut InferenceContext<'_>, solution: Canonical<Vec<Ty>>) { 144 pub fn apply_solution(&self, ctx: &mut InferenceContext<'_>, solution: Canonical<Substs>) {
135 // the solution may contain new variables, which we need to convert to new inference vars 145 // the solution may contain new variables, which we need to convert to new inference vars
136 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.table.new_type_var()).collect()); 146 let new_vars = Substs(
147 solution
148 .kinds
149 .iter()
150 .map(|k| match k {
151 TyKind::General => ctx.table.new_type_var(),
152 TyKind::Integer => ctx.table.new_integer_var(),
153 TyKind::Float => ctx.table.new_float_var(),
154 })
155 .collect(),
156 );
137 for (i, ty) in solution.value.into_iter().enumerate() { 157 for (i, ty) in solution.value.into_iter().enumerate() {
138 let var = self.free_vars[i]; 158 let var = self.free_vars[i];
139 // eagerly replace projections in the type; we may be getting types 159 // eagerly replace projections in the type; we may be getting types
140 // e.g. from where clauses where this hasn't happened yet 160 // e.g. from where clauses where this hasn't happened yet
141 let ty = ctx.normalize_associated_types_in(ty.subst_bound_vars(&new_vars)); 161 let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars));
142 ctx.table.unify(&Ty::Infer(var), &ty); 162 ctx.table.unify(&Ty::Infer(var), &ty);
143 } 163 }
144 } 164 }
145} 165}
146 166
147pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> { 167pub fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> {
148 let mut table = InferenceTable::new(); 168 let mut table = InferenceTable::new();
149 let num_vars = ty1.num_vars.max(ty2.num_vars); 169 let vars = Substs(
150 let vars = 170 tys.kinds
151 Substs::builder(num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); 171 .iter()
152 let ty1_with_vars = ty1.value.clone().subst_bound_vars(&vars); 172 // we always use type vars here because we want everything to
153 let ty2_with_vars = ty2.value.clone().subst_bound_vars(&vars); 173 // fallback to Unknown in the end (kind of hacky, as below)
174 .map(|_| table.new_type_var())
175 .collect(),
176 );
177 let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars);
178 let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars);
154 if !table.unify(&ty1_with_vars, &ty2_with_vars) { 179 if !table.unify(&ty1_with_vars, &ty2_with_vars) {
155 return None; 180 return None;
156 } 181 }
@@ -162,7 +187,7 @@ pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
162 } 187 }
163 } 188 }
164 Some( 189 Some(
165 Substs::builder(ty1.num_vars) 190 Substs::builder(tys.kinds.len())
166 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) 191 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
167 .build(), 192 .build(),
168 ) 193 )
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index c9513b752..7f3f5e771 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -662,13 +662,27 @@ impl TypeWalk for GenericPredicate {
662 662
663/// Basically a claim (currently not validated / checked) that the contained 663/// Basically a claim (currently not validated / checked) that the contained
664/// type / trait ref contains no inference variables; any inference variables it 664/// type / trait ref contains no inference variables; any inference variables it
665/// contained have been replaced by bound variables, and `num_vars` tells us how 665/// contained have been replaced by bound variables, and `kinds` tells us how
666/// many there are. This is used to erase irrelevant differences between types 666/// many there are and whether they were normal or float/int variables. This is
667/// before using them in queries. 667/// used to erase irrelevant differences between types before using them in
668/// queries.
668#[derive(Debug, Clone, PartialEq, Eq, Hash)] 669#[derive(Debug, Clone, PartialEq, Eq, Hash)]
669pub struct Canonical<T> { 670pub struct Canonical<T> {
670 pub value: T, 671 pub value: T,
671 pub num_vars: usize, 672 pub kinds: Arc<[TyKind]>,
673}
674
675impl<T> Canonical<T> {
676 pub fn new(value: T, kinds: impl IntoIterator<Item = TyKind>) -> Self {
677 Self { value, kinds: kinds.into_iter().collect() }
678 }
679}
680
681#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
682pub enum TyKind {
683 General,
684 Integer,
685 Float,
672} 686}
673 687
674/// A function signature as seen by type inference: Several parameter types and 688/// A function signature as seen by type inference: Several parameter types and
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 5dbabd12b..a45febbf7 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -2,7 +2,7 @@
2//! For details about how this works in rustc, see the method lookup page in the 2//! For details about how this works in rustc, see the method lookup page in the
3//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html) 3//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
4//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs. 4//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
5use std::sync::Arc; 5use std::{iter, sync::Arc};
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
@@ -17,7 +17,8 @@ use rustc_hash::{FxHashMap, FxHashSet};
17use super::Substs; 17use super::Substs;
18use crate::{ 18use crate::{
19 autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy, 19 autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy,
20 Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 20 Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor,
21 TypeWalk,
21}; 22};
22 23
23/// This is used as a key for indexing impls. 24/// This is used as a key for indexing impls.
@@ -372,7 +373,7 @@ fn iterate_method_candidates_with_autoref(
372 return true; 373 return true;
373 } 374 }
374 let refed = Canonical { 375 let refed = Canonical {
375 num_vars: deref_chain[0].num_vars, 376 kinds: deref_chain[0].kinds.clone(),
376 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), 377 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()),
377 }; 378 };
378 if iterate_method_candidates_by_receiver( 379 if iterate_method_candidates_by_receiver(
@@ -388,7 +389,7 @@ fn iterate_method_candidates_with_autoref(
388 return true; 389 return true;
389 } 390 }
390 let ref_muted = Canonical { 391 let ref_muted = Canonical {
391 num_vars: deref_chain[0].num_vars, 392 kinds: deref_chain[0].kinds.clone(),
392 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), 393 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()),
393 }; 394 };
394 if iterate_method_candidates_by_receiver( 395 if iterate_method_candidates_by_receiver(
@@ -607,18 +608,19 @@ pub(crate) fn inherent_impl_substs(
607 // we create a var for each type parameter of the impl; we need to keep in 608 // we create a var for each type parameter of the impl; we need to keep in
608 // mind here that `self_ty` might have vars of its own 609 // mind here that `self_ty` might have vars of its own
609 let vars = Substs::build_for_def(db, impl_id) 610 let vars = Substs::build_for_def(db, impl_id)
610 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.num_vars) 611 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.kinds.len())
611 .build(); 612 .build();
612 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 613 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
613 let self_ty_with_vars = 614 let mut kinds = self_ty.kinds.to_vec();
614 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars }; 615 kinds.extend(iter::repeat(TyKind::General).take(vars.len()));
615 let substs = super::infer::unify(&self_ty_with_vars, self_ty); 616 let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) };
617 let substs = super::infer::unify(&tys);
616 // We only want the substs for the vars we added, not the ones from self_ty. 618 // We only want the substs for the vars we added, not the ones from self_ty.
617 // Also, if any of the vars we added are still in there, we replace them by 619 // Also, if any of the vars we added are still in there, we replace them by
618 // Unknown. I think this can only really happen if self_ty contained 620 // Unknown. I think this can only really happen if self_ty contained
619 // Unknown, and in that case we want the result to contain Unknown in those 621 // Unknown, and in that case we want the result to contain Unknown in those
620 // places again. 622 // places again.
621 substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.num_vars)) 623 substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.kinds.len()))
622} 624}
623 625
624/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 626/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
@@ -678,15 +680,15 @@ fn generic_implements_goal(
678 trait_: TraitId, 680 trait_: TraitId,
679 self_ty: Canonical<Ty>, 681 self_ty: Canonical<Ty>,
680) -> Canonical<InEnvironment<super::Obligation>> { 682) -> Canonical<InEnvironment<super::Obligation>> {
681 let num_vars = self_ty.num_vars; 683 let mut kinds = self_ty.kinds.to_vec();
682 let substs = super::Substs::build_for_def(db, trait_) 684 let substs = super::Substs::build_for_def(db, trait_)
683 .push(self_ty.value) 685 .push(self_ty.value)
684 .fill_with_bound_vars(DebruijnIndex::INNERMOST, num_vars) 686 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
685 .build(); 687 .build();
686 let num_vars = substs.len() - 1 + self_ty.num_vars; 688 kinds.extend(iter::repeat(TyKind::General).take(substs.len() - 1));
687 let trait_ref = TraitRef { trait_, substs }; 689 let trait_ref = TraitRef { trait_, substs };
688 let obligation = super::Obligation::Trait(trait_ref); 690 let obligation = super::Obligation::Trait(trait_ref);
689 Canonical { num_vars, value: InEnvironment::new(env, obligation) } 691 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
690} 692}
691 693
692fn autoderef_method_receiver( 694fn autoderef_method_receiver(
@@ -699,9 +701,9 @@ fn autoderef_method_receiver(
699 if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) = 701 if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) =
700 deref_chain.last().map(|ty| &ty.value) 702 deref_chain.last().map(|ty| &ty.value)
701 { 703 {
702 let num_vars = deref_chain.last().unwrap().num_vars; 704 let kinds = deref_chain.last().unwrap().kinds.clone();
703 let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone()); 705 let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone());
704 deref_chain.push(Canonical { value: unsized_ty, num_vars }) 706 deref_chain.push(Canonical { value: unsized_ty, kinds })
705 } 707 }
706 deref_chain 708 deref_chain
707} 709}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 01c919a7e..766790576 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -3029,3 +3029,21 @@ fn infer_dyn_fn_output() {
3029 "### 3029 "###
3030 ); 3030 );
3031} 3031}
3032
3033#[test]
3034fn variable_kinds() {
3035 check_types(
3036 r#"
3037trait Trait<T> { fn get(self, t: T) -> T; }
3038struct S;
3039impl Trait<u128> for S {}
3040impl Trait<f32> for S {}
3041fn test() {
3042 S.get(1);
3043 //^^^^^^^^ u128
3044 S.get(1.);
3045 //^^^^^^^^ f32
3046}
3047 "#,
3048 );
3049}
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index 6f43c3a22..2a6d7faef 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -1,5 +1,5 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2use std::{panic, sync::Arc}; 2use std::sync::Arc;
3 3
4use chalk_ir::cast::Cast; 4use chalk_ir::cast::Cast;
5use hir_def::{ 5use hir_def::{
@@ -8,7 +8,7 @@ use hir_def::{
8use ra_db::{impl_intern_key, salsa, CrateId}; 8use ra_db::{impl_intern_key, salsa, CrateId};
9use ra_prof::profile; 9use ra_prof::profile;
10 10
11use crate::{db::HirDatabase, DebruijnIndex}; 11use crate::{db::HirDatabase, DebruijnIndex, Substs};
12 12
13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
14 14
@@ -190,15 +190,7 @@ fn solution_from_chalk(
190 solution: chalk_solve::Solution<Interner>, 190 solution: chalk_solve::Solution<Interner>,
191) -> Solution { 191) -> Solution {
192 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| { 192 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| {
193 let value = subst 193 let result = from_chalk(db, subst);
194 .value
195 .iter(&Interner)
196 .map(|p| match p.ty(&Interner) {
197 Some(ty) => from_chalk(db, ty.clone()),
198 None => unimplemented!(),
199 })
200 .collect();
201 let result = Canonical { value, num_vars: subst.binders.len(&Interner) };
202 SolutionVariables(result) 194 SolutionVariables(result)
203 }; 195 };
204 match solution { 196 match solution {
@@ -222,7 +214,7 @@ fn solution_from_chalk(
222} 214}
223 215
224#[derive(Clone, Debug, PartialEq, Eq)] 216#[derive(Clone, Debug, PartialEq, Eq)]
225pub struct SolutionVariables(pub Canonical<Vec<Ty>>); 217pub struct SolutionVariables(pub Canonical<Substs>);
226 218
227#[derive(Clone, Debug, PartialEq, Eq)] 219#[derive(Clone, Debug, PartialEq, Eq)]
228/// A (possible) solution for a proposed goal. 220/// A (possible) solution for a proposed goal.
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
index ac82ea831..433d6aa03 100644
--- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
@@ -17,7 +17,7 @@ use crate::{
17 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, 17 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness},
18 traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, 18 traits::{builtin, AssocTyValue, Canonical, Impl, Obligation},
19 ApplicationTy, CallableDef, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, 19 ApplicationTy, CallableDef, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId,
20 ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, 20 ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor,
21}; 21};
22 22
23use super::interner::*; 23use super::interner::*;
@@ -555,22 +555,39 @@ where
555 type Chalk = chalk_ir::Canonical<T::Chalk>; 555 type Chalk = chalk_ir::Canonical<T::Chalk>;
556 556
557 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { 557 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
558 let parameter = chalk_ir::CanonicalVarKind::new( 558 let kinds = self
559 chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General), 559 .kinds
560 chalk_ir::UniverseIndex::ROOT, 560 .iter()
561 ); 561 .map(|k| match k {
562 TyKind::General => chalk_ir::TyKind::General,
563 TyKind::Integer => chalk_ir::TyKind::Integer,
564 TyKind::Float => chalk_ir::TyKind::Float,
565 })
566 .map(|tk| {
567 chalk_ir::CanonicalVarKind::new(
568 chalk_ir::VariableKind::Ty(tk),
569 chalk_ir::UniverseIndex::ROOT,
570 )
571 });
562 let value = self.value.to_chalk(db); 572 let value = self.value.to_chalk(db);
563 chalk_ir::Canonical { 573 chalk_ir::Canonical { value, binders: chalk_ir::CanonicalVarKinds::from(&Interner, kinds) }
564 value,
565 binders: chalk_ir::CanonicalVarKinds::from(&Interner, vec![parameter; self.num_vars]),
566 }
567 } 574 }
568 575
569 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { 576 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
570 Canonical { 577 let kinds = canonical
571 num_vars: canonical.binders.len(&Interner), 578 .binders
572 value: from_chalk(db, canonical.value), 579 .iter(&Interner)
573 } 580 .map(|k| match k.kind {
581 chalk_ir::VariableKind::Ty(tk) => match tk {
582 chalk_ir::TyKind::General => TyKind::General,
583 chalk_ir::TyKind::Integer => TyKind::Integer,
584 chalk_ir::TyKind::Float => TyKind::Float,
585 },
586 chalk_ir::VariableKind::Lifetime => panic!("unexpected lifetime from Chalk"),
587 chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
588 })
589 .collect();
590 Canonical { kinds, value: from_chalk(db, canonical.value) }
574 } 591 }
575} 592}
576 593