aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/db.rs17
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs16
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs5
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs7
-rw-r--r--crates/ra_hir_ty/src/lib.rs49
-rw-r--r--crates/ra_hir_ty/src/lower.rs108
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs2
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs2
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs3
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs24
-rw-r--r--crates/ra_hir_ty/src/utils.rs30
11 files changed, 136 insertions, 127 deletions
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index fea122a8b..7684ade06 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -3,10 +3,10 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId, 6 db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId, TypeParamId,
7}; 7};
8use ra_arena::map::ArenaMap; 8use ra_arena::map::ArenaMap;
9use ra_db::{salsa, CrateId}; 9use ra_db::{impl_intern_key, salsa, CrateId};
10use ra_prof::profile; 10use ra_prof::profile;
11 11
12use crate::{ 12use crate::{
@@ -37,10 +37,10 @@ pub trait HirDatabase: DefDatabase {
37 fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>; 37 fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
38 38
39 #[salsa::invoke(crate::lower::impl_trait_query)] 39 #[salsa::invoke(crate::lower::impl_trait_query)]
40 fn impl_trait(&self, def: ImplId) -> Option<TraitRef>; 40 fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
41 41
42 #[salsa::invoke(crate::lower::field_types_query)] 42 #[salsa::invoke(crate::lower::field_types_query)]
43 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; 43 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>>;
44 44
45 #[salsa::invoke(crate::callable_item_sig)] 45 #[salsa::invoke(crate::callable_item_sig)]
46 fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig; 46 fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig;
@@ -49,8 +49,7 @@ pub trait HirDatabase: DefDatabase {
49 #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] 49 #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
50 fn generic_predicates_for_param( 50 fn generic_predicates_for_param(
51 &self, 51 &self,
52 def: GenericDefId, 52 param_id: TypeParamId,
53 param_idx: u32,
54 ) -> Arc<[GenericPredicate]>; 53 ) -> Arc<[GenericPredicate]>;
55 54
56 #[salsa::invoke(crate::lower::generic_predicates_query)] 55 #[salsa::invoke(crate::lower::generic_predicates_query)]
@@ -77,6 +76,8 @@ pub trait HirDatabase: DefDatabase {
77 #[salsa::interned] 76 #[salsa::interned]
78 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; 77 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId;
79 #[salsa::interned] 78 #[salsa::interned]
79 fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId;
80 #[salsa::interned]
80 fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; 81 fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
81 #[salsa::interned] 82 #[salsa::interned]
82 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; 83 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
@@ -117,3 +118,7 @@ fn infer(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
117fn hir_database_is_object_safe() { 118fn hir_database_is_object_safe() {
118 fn _assert_object_safe(_: &dyn HirDatabase) {} 119 fn _assert_object_safe(_: &dyn HirDatabase) {}
119} 120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
123pub struct GlobalTypeParamId(salsa::InternId);
124impl_intern_key!(GlobalTypeParamId);
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 83c0c2c3f..2a9567898 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -57,8 +57,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
57 let trait_ref = db.impl_trait(impl_id)?; 57 let trait_ref = db.impl_trait(impl_id)?;
58 58
59 // `CoerseUnsized` has one generic parameter for the target type. 59 // `CoerseUnsized` has one generic parameter for the target type.
60 let cur_from_ty = trait_ref.substs.0.get(0)?; 60 let cur_from_ty = trait_ref.value.substs.0.get(0)?;
61 let cur_to_ty = trait_ref.substs.0.get(1)?; 61 let cur_to_ty = trait_ref.value.substs.0.get(1)?;
62 62
63 match (&cur_from_ty, cur_to_ty) { 63 match (&cur_from_ty, cur_to_ty) {
64 (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => { 64 (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => {
@@ -66,8 +66,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
66 // This works for smart-pointer-like coercion, which covers all impls from std. 66 // This works for smart-pointer-like coercion, which covers all impls from std.
67 st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| { 67 st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| {
68 match (ty1, ty2) { 68 match (ty1, ty2) {
69 (Ty::Param { idx: p1, .. }, Ty::Param { idx: p2, .. }) 69 (Ty::Bound(idx1), Ty::Bound(idx2))
70 if p1 != p2 => 70 if idx1 != idx2 =>
71 { 71 {
72 Some(((*ctor1, *ctor2), i)) 72 Some(((*ctor1, *ctor2), i))
73 } 73 }
@@ -256,8 +256,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
256 let unsize_generic_index = { 256 let unsize_generic_index = {
257 let mut index = None; 257 let mut index = None;
258 let mut multiple_param = false; 258 let mut multiple_param = false;
259 field_tys[last_field_id].walk(&mut |ty| match ty { 259 field_tys[last_field_id].value.walk(&mut |ty| match ty {
260 &Ty::Param { idx, .. } => { 260 &Ty::Bound(idx) => {
261 if index.is_none() { 261 if index.is_none() {
262 index = Some(idx); 262 index = Some(idx);
263 } else if Some(idx) != index { 263 } else if Some(idx) != index {
@@ -276,8 +276,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
276 // Check other fields do not involve it. 276 // Check other fields do not involve it.
277 let mut multiple_used = false; 277 let mut multiple_used = false;
278 fields.for_each(|(field_id, _data)| { 278 fields.for_each(|(field_id, _data)| {
279 field_tys[field_id].walk(&mut |ty| match ty { 279 field_tys[field_id].value.walk(&mut |ty| match ty {
280 &Ty::Param { idx, .. } if idx == unsize_generic_index => { 280 &Ty::Bound(idx) if idx == unsize_generic_index => {
281 multiple_used = true 281 multiple_used = true
282 } 282 }
283 _ => {} 283 _ => {}
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index e1fdb356d..8b8378499 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -236,8 +236,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
236 self.result.record_field_resolutions.insert(field.expr, field_def); 236 self.result.record_field_resolutions.insert(field.expr, field_def);
237 } 237 }
238 let field_ty = field_def 238 let field_ty = field_def
239 .map_or(Ty::Unknown, |it| field_types[it.local_id].clone()) 239 .map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs));
240 .subst(&substs);
241 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); 240 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
242 } 241 }
243 if let Some(expr) = spread { 242 if let Some(expr) = spread {
@@ -686,7 +685,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
686 if let TypeCtor::FnDef(def) = a_ty.ctor { 685 if let TypeCtor::FnDef(def) = a_ty.ctor {
687 let generic_predicates = self.db.generic_predicates(def.into()); 686 let generic_predicates = self.db.generic_predicates(def.into());
688 for predicate in generic_predicates.iter() { 687 for predicate in generic_predicates.iter() {
689 let predicate = predicate.clone().subst(&a_ty.parameters); 688 let predicate = predicate.clone().subst_type_params(self.db, def.into(), &a_ty.parameters);
690 if let Some(obligation) = Obligation::from_predicate(predicate) { 689 if let Some(obligation) = Obligation::from_predicate(predicate) {
691 self.obligations.push(obligation); 690 self.obligations.push(obligation);
692 } 691 }
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index a14662884..e7283f24c 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -12,7 +12,7 @@ use hir_expand::name::Name;
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use super::{BindingMode, InferenceContext}; 14use super::{BindingMode, InferenceContext};
15use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, TypeWalk}; 15use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor};
16 16
17impl<'a, D: HirDatabase> InferenceContext<'a, D> { 17impl<'a, D: HirDatabase> InferenceContext<'a, D> {
18 fn infer_tuple_struct_pat( 18 fn infer_tuple_struct_pat(
@@ -34,8 +34,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
34 let expected_ty = var_data 34 let expected_ty = var_data
35 .as_ref() 35 .as_ref()
36 .and_then(|d| d.field(&Name::new_tuple_field(i))) 36 .and_then(|d| d.field(&Name::new_tuple_field(i)))
37 .map_or(Ty::Unknown, |field| field_tys[field].clone()) 37 .map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
38 .subst(&substs);
39 let expected_ty = self.normalize_associated_types_in(expected_ty); 38 let expected_ty = self.normalize_associated_types_in(expected_ty);
40 self.infer_pat(subpat, &expected_ty, default_bm); 39 self.infer_pat(subpat, &expected_ty, default_bm);
41 } 40 }
@@ -65,7 +64,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
65 for subpat in subpats { 64 for subpat in subpats {
66 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); 65 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
67 let expected_ty = 66 let expected_ty =
68 matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs); 67 matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
69 let expected_ty = self.normalize_associated_types_in(expected_ty); 68 let expected_ty = self.normalize_associated_types_in(expected_ty);
70 self.infer_pat(subpat.pat, &expected_ty, default_bm); 69 self.infer_pat(subpat.pat, &expected_ty, default_bm);
71 } 70 }
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 1f0fd1128..1e162943c 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -45,10 +45,10 @@ use std::{fmt, iter, mem};
45 45
46use hir_def::{ 46use hir_def::{
47 expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, 47 expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
48 HasModule, Lookup, TraitId, TypeAliasId, 48 HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, generics::TypeParamProvenance,
49}; 49};
50use hir_expand::name::Name;
51use ra_db::{impl_intern_key, salsa, CrateId}; 50use ra_db::{impl_intern_key, salsa, CrateId};
51use hir_expand::name::Name;
52 52
53use crate::{ 53use crate::{
54 db::HirDatabase, 54 db::HirDatabase,
@@ -288,14 +288,7 @@ pub enum Ty {
288 Projection(ProjectionTy), 288 Projection(ProjectionTy),
289 289
290 /// A type parameter; for example, `T` in `fn f<T>(x: T) {} 290 /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
291 Param { 291 Param(TypeParamId),
292 /// The index of the parameter (starting with parameters from the
293 /// surrounding impl, then the current function).
294 idx: u32,
295 /// The name of the parameter, for displaying.
296 // FIXME get rid of this
297 name: Name,
298 },
299 292
300 /// A bound type variable. Used during trait resolution to represent Chalk 293 /// A bound type variable. Used during trait resolution to represent Chalk
301 /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type. 294 /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
@@ -366,15 +359,15 @@ impl Substs {
366 } 359 }
367 360
368 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). 361 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
369 pub(crate) fn identity(generic_params: &Generics) -> Substs { 362 pub(crate) fn type_params(generic_params: &Generics) -> Substs {
370 Substs( 363 Substs(
371 generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone().unwrap_or_else(Name::missing) }).collect(), 364 generic_params.iter().map(|(id, _)| Ty::Param(id)).collect(),
372 ) 365 )
373 } 366 }
374 367
375 /// Return Substs that replace each parameter by a bound variable. 368 /// Return Substs that replace each parameter by a bound variable.
376 pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { 369 pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
377 Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect()) 370 Substs(generic_params.iter().enumerate().map(|(idx, _)| Ty::Bound(idx as u32)).collect())
378 } 371 }
379 372
380 pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { 373 pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
@@ -422,11 +415,6 @@ impl SubstsBuilder {
422 self.fill((starting_from..).map(Ty::Bound)) 415 self.fill((starting_from..).map(Ty::Bound))
423 } 416 }
424 417
425 pub fn fill_with_params(self) -> Self {
426 let start = self.vec.len() as u32;
427 self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() }))
428 }
429
430 pub fn fill_with_unknown(self) -> Self { 418 pub fn fill_with_unknown(self) -> Self {
431 self.fill(iter::repeat(Ty::Unknown)) 419 self.fill(iter::repeat(Ty::Unknown))
432 } 420 }
@@ -762,13 +750,19 @@ pub trait TypeWalk {
762 /// Replaces type parameters in this type using the given `Substs`. (So e.g. 750 /// Replaces type parameters in this type using the given `Substs`. (So e.g.
763 /// if `self` is `&[T]`, where type parameter T has index 0, and the 751 /// if `self` is `&[T]`, where type parameter T has index 0, and the
764 /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) 752 /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
765 fn subst(self, substs: &Substs) -> Self 753 // TODO: this should mostly not be used anymore
754 fn subst_type_params(self, db: &impl HirDatabase, def: GenericDefId, substs: &Substs) -> Self
766 where 755 where
767 Self: Sized, 756 Self: Sized,
768 { 757 {
758 let generics = generics(db, def);
769 self.fold(&mut |ty| match ty { 759 self.fold(&mut |ty| match ty {
770 Ty::Param { idx, name } => { 760 Ty::Param(id) => {
771 substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name }) 761 if let Some(idx) = generics.param_idx(id) {
762 substs.get(idx as usize).cloned().unwrap_or(Ty::Param(id))
763 } else {
764 ty
765 }
772 } 766 }
773 ty => ty, 767 ty => ty,
774 }) 768 })
@@ -1042,7 +1036,18 @@ impl HirDisplay for Ty {
1042 match self { 1036 match self {
1043 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, 1037 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
1044 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, 1038 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
1045 Ty::Param { name, .. } => write!(f, "{}", name)?, 1039 Ty::Param(id) => {
1040 let generic_params = f.db.generic_params(id.parent);
1041 let param_data = &generic_params.types[id.local_id];
1042 match param_data.provenance {
1043 TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
1044 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
1045 }
1046 TypeParamProvenance::ArgumentImplTrait => {
1047 write!(f, "impl TODO")?
1048 }
1049 }
1050 },
1046 Ty::Bound(idx) => write!(f, "?{}", idx)?, 1051 Ty::Bound(idx) => write!(f, "?{}", idx)?,
1047 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 1052 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
1048 match self { 1053 match self {
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 88d962b47..d60b59433 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -30,7 +30,7 @@ use crate::{
30 Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, 30 Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
31 TraitEnvironment, TraitRef, Ty, TypeCtor, 31 TraitEnvironment, TraitRef, Ty, TypeCtor,
32}; 32};
33use hir_expand::name::Name; 33use hir_def::TypeParamId;
34 34
35#[derive(Debug)] 35#[derive(Debug)]
36pub struct TyLoweringContext<'a, DB: HirDatabase> { 36pub struct TyLoweringContext<'a, DB: HirDatabase> {
@@ -145,7 +145,16 @@ impl Ty {
145 ImplTraitLoweringMode::Param => { 145 ImplTraitLoweringMode::Param => {
146 let idx = ctx.impl_trait_counter.get(); 146 let idx = ctx.impl_trait_counter.get();
147 ctx.impl_trait_counter.set(idx + 1); 147 ctx.impl_trait_counter.set(idx + 1);
148 Ty::Param { idx: idx as u32, name: Name::missing() } 148 if let Some(def) = ctx.resolver.generic_def() {
149 let generics = generics(ctx.db, def);
150 let param = generics
151 .iter()
152 .nth(idx as usize)
153 .map_or(Ty::Unknown, |(id, _)| Ty::Param(id));
154 param
155 } else {
156 Ty::Unknown
157 }
149 } 158 }
150 ImplTraitLoweringMode::Variable => { 159 ImplTraitLoweringMode::Variable => {
151 let idx = ctx.impl_trait_counter.get(); 160 let idx = ctx.impl_trait_counter.get();
@@ -176,7 +185,7 @@ impl Ty {
176 fn from_hir_only_param( 185 fn from_hir_only_param(
177 ctx: &TyLoweringContext<'_, impl HirDatabase>, 186 ctx: &TyLoweringContext<'_, impl HirDatabase>,
178 type_ref: &TypeRef, 187 type_ref: &TypeRef,
179 ) -> Option<u32> { 188 ) -> Option<TypeParamId> {
180 let path = match type_ref { 189 let path = match type_ref {
181 TypeRef::Path(path) => path, 190 TypeRef::Path(path) => path,
182 _ => return None, 191 _ => return None,
@@ -192,9 +201,7 @@ impl Ty {
192 _ => return None, 201 _ => return None,
193 }; 202 };
194 if let TypeNs::GenericParam(param_id) = resolution { 203 if let TypeNs::GenericParam(param_id) = resolution {
195 let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); 204 Some(param_id)
196 let idx = generics.param_idx(param_id);
197 Some(idx)
198 } else { 205 } else {
199 None 206 None
200 } 207 }
@@ -256,20 +263,18 @@ impl Ty {
256 TypeNs::GenericParam(param_id) => { 263 TypeNs::GenericParam(param_id) => {
257 let generics = 264 let generics =
258 generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); 265 generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope"));
259 let idx = generics.param_idx(param_id);
260 match ctx.type_param_mode { 266 match ctx.type_param_mode {
261 TypeParamLoweringMode::Placeholder => { 267 TypeParamLoweringMode::Placeholder => Ty::Param(param_id),
262 // FIXME: maybe return name in resolution? 268 TypeParamLoweringMode::Variable => {
263 let name = generics.param_name(param_id); 269 let idx = generics.param_idx(param_id).expect("matching generics");
264 Ty::Param { idx, name } 270 Ty::Bound(idx)
265 } 271 }
266 TypeParamLoweringMode::Variable => Ty::Bound(idx),
267 } 272 }
268 } 273 }
269 TypeNs::SelfType(impl_id) => { 274 TypeNs::SelfType(impl_id) => {
270 let generics = generics(ctx.db, impl_id.into()); 275 let generics = generics(ctx.db, impl_id.into());
271 let substs = match ctx.type_param_mode { 276 let substs = match ctx.type_param_mode {
272 TypeParamLoweringMode::Placeholder => Substs::identity(&generics), 277 TypeParamLoweringMode::Placeholder => Substs::type_params(&generics),
273 TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), 278 TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
274 }; 279 };
275 ctx.db.impl_self_ty(impl_id).subst(&substs) 280 ctx.db.impl_self_ty(impl_id).subst(&substs)
@@ -277,7 +282,7 @@ impl Ty {
277 TypeNs::AdtSelfType(adt) => { 282 TypeNs::AdtSelfType(adt) => {
278 let generics = generics(ctx.db, adt.into()); 283 let generics = generics(ctx.db, adt.into());
279 let substs = match ctx.type_param_mode { 284 let substs = match ctx.type_param_mode {
280 TypeParamLoweringMode::Placeholder => Substs::identity(&generics), 285 TypeParamLoweringMode::Placeholder => Substs::type_params(&generics),
281 TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), 286 TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
282 }; 287 };
283 ctx.db.ty(adt.into()).subst(&substs) 288 ctx.db.ty(adt.into()).subst(&substs)
@@ -319,20 +324,28 @@ impl Ty {
319 self_ty: Ty, 324 self_ty: Ty,
320 segment: PathSegment<'_>, 325 segment: PathSegment<'_>,
321 ) -> Ty { 326 ) -> Ty {
322 let param_idx = match self_ty {
323 Ty::Param { idx, .. } if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => idx,
324 Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => idx,
325 _ => return Ty::Unknown, // Error: Ambiguous associated type
326 };
327 let def = match ctx.resolver.generic_def() { 327 let def = match ctx.resolver.generic_def() {
328 Some(def) => def, 328 Some(def) => def,
329 None => return Ty::Unknown, // this can't actually happen 329 None => return Ty::Unknown, // this can't actually happen
330 }; 330 };
331 let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx); 331 let param_id = match self_ty {
332 Ty::Param(id) if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => id,
333 Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => {
334 let generics = generics(ctx.db, def);
335 let param_id = if let Some((id, _)) = generics.iter().nth(idx as usize) {
336 id
337 } else {
338 return Ty::Unknown;
339 };
340 param_id
341 },
342 _ => return Ty::Unknown, // Error: Ambiguous associated type
343 };
344 let predicates = ctx.db.generic_predicates_for_param(param_id);
332 let traits_from_env = predicates.iter().filter_map(|pred| match pred { 345 let traits_from_env = predicates.iter().filter_map(|pred| match pred {
333 GenericPredicate::Implemented(tr) => { 346 GenericPredicate::Implemented(tr) => {
334 if let Ty::Param { idx, .. } = tr.self_ty() { 347 if let Ty::Param(id) = tr.self_ty() {
335 if *idx == param_idx { 348 if *id == param_id {
336 return Some(tr.trait_); 349 return Some(tr.trait_);
337 } 350 }
338 } 351 }
@@ -530,13 +543,12 @@ impl GenericPredicate {
530 let generic_def = ctx.resolver.generic_def().expect("generics in scope"); 543 let generic_def = ctx.resolver.generic_def().expect("generics in scope");
531 let generics = generics(ctx.db, generic_def); 544 let generics = generics(ctx.db, generic_def);
532 let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; 545 let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
533 let idx = generics.param_idx(param_id);
534 match ctx.type_param_mode { 546 match ctx.type_param_mode {
535 TypeParamLoweringMode::Placeholder => { 547 TypeParamLoweringMode::Placeholder => Ty::Param(param_id),
536 let name = generics.param_name(param_id); 548 TypeParamLoweringMode::Variable => {
537 Ty::Param { idx, name } 549 let idx = generics.param_idx(param_id).expect("matching generics");
550 Ty::Bound(idx)
538 } 551 }
539 TypeParamLoweringMode::Variable => Ty::Bound(idx),
540 } 552 }
541 } 553 }
542 }; 554 };
@@ -599,17 +611,19 @@ pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig {
599pub(crate) fn field_types_query( 611pub(crate) fn field_types_query(
600 db: &impl HirDatabase, 612 db: &impl HirDatabase,
601 variant_id: VariantId, 613 variant_id: VariantId,
602) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { 614) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>> {
603 let var_data = variant_data(db, variant_id); 615 let var_data = variant_data(db, variant_id);
604 let resolver = match variant_id { 616 let (resolver, def): (_, GenericDefId) = match variant_id {
605 VariantId::StructId(it) => it.resolver(db), 617 VariantId::StructId(it) => (it.resolver(db), it.into()),
606 VariantId::UnionId(it) => it.resolver(db), 618 VariantId::UnionId(it) => (it.resolver(db), it.into()),
607 VariantId::EnumVariantId(it) => it.parent.resolver(db), 619 VariantId::EnumVariantId(it) => (it.parent.resolver(db), it.parent.into()),
608 }; 620 };
621 let generics = generics(db, def);
609 let mut res = ArenaMap::default(); 622 let mut res = ArenaMap::default();
610 let ctx = TyLoweringContext::new(db, &resolver); 623 let ctx = TyLoweringContext::new(db, &resolver)
624 .with_type_param_mode(TypeParamLoweringMode::Variable);
611 for (field_id, field_data) in var_data.fields().iter() { 625 for (field_id, field_data) in var_data.fields().iter() {
612 res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref)) 626 res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref)))
613 } 627 }
614 Arc::new(res) 628 Arc::new(res)
615} 629}
@@ -624,23 +638,20 @@ pub(crate) fn field_types_query(
624/// these are fine: `T: Foo<U::Item>, U: Foo<()>`. 638/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
625pub(crate) fn generic_predicates_for_param_query( 639pub(crate) fn generic_predicates_for_param_query(
626 db: &impl HirDatabase, 640 db: &impl HirDatabase,
627 def: GenericDefId, 641 param_id: TypeParamId,
628 param_idx: u32,
629) -> Arc<[GenericPredicate]> { 642) -> Arc<[GenericPredicate]> {
630 let resolver = def.resolver(db); 643 let resolver = param_id.parent.resolver(db);
631 let ctx = TyLoweringContext::new(db, &resolver); 644 let ctx = TyLoweringContext::new(db, &resolver);
632 let generics = generics(db, def); 645 // let generics = generics(db, def);
633 resolver 646 resolver
634 .where_predicates_in_scope() 647 .where_predicates_in_scope()
635 // we have to filter out all other predicates *first*, before attempting to lower them 648 // we have to filter out all other predicates *first*, before attempting to lower them
636 .filter(|pred| match &pred.target { 649 .filter(|pred| match &pred.target {
637 WherePredicateTarget::TypeRef(type_ref) => { 650 WherePredicateTarget::TypeRef(type_ref) => {
638 Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx) 651 Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
639 } 652 }
640 WherePredicateTarget::TypeParam(local_id) => { 653 WherePredicateTarget::TypeParam(local_id) => {
641 let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; 654 *local_id == param_id.local_id
642 let idx = generics.param_idx(param_id);
643 idx == param_idx
644 } 655 }
645 }) 656 })
646 .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) 657 .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred))
@@ -650,8 +661,7 @@ pub(crate) fn generic_predicates_for_param_query(
650pub(crate) fn generic_predicates_for_param_recover( 661pub(crate) fn generic_predicates_for_param_recover(
651 _db: &impl HirDatabase, 662 _db: &impl HirDatabase,
652 _cycle: &[String], 663 _cycle: &[String],
653 _def: &GenericDefId, 664 _param_id: &TypeParamId,
654 _param_idx: &u32,
655) -> Arc<[GenericPredicate]> { 665) -> Arc<[GenericPredicate]> {
656 Arc::new([]) 666 Arc::new([])
657} 667}
@@ -905,12 +915,12 @@ pub(crate) fn impl_self_ty_recover(
905 Binders::new(generics.len(), Ty::Unknown) 915 Binders::new(generics.len(), Ty::Unknown)
906} 916}
907 917
908pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> { 918pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
909 let impl_data = db.impl_data(impl_id); 919 let impl_data = db.impl_data(impl_id);
910 let resolver = impl_id.resolver(db); 920 let resolver = impl_id.resolver(db);
911 let generics = generics(db, impl_id.into()); 921 let ctx = TyLoweringContext::new(db, &resolver)
912 let ctx = TyLoweringContext::new(db, &resolver); 922 .with_type_param_mode(TypeParamLoweringMode::Variable);
913 let self_ty = db.impl_self_ty(impl_id).subst(&Substs::identity(&generics)); 923 let self_ty = db.impl_self_ty(impl_id);
914 let target_trait = impl_data.target_trait.as_ref()?; 924 let target_trait = impl_data.target_trait.as_ref()?;
915 TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone())) 925 Some(Binders::new(self_ty.num_binders, TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?))
916} 926}
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index eab2149dc..5283bff28 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -61,7 +61,7 @@ impl CrateImplBlocks {
61 for impl_id in module_data.scope.impls() { 61 for impl_id in module_data.scope.impls() {
62 match db.impl_trait(impl_id) { 62 match db.impl_trait(impl_id) {
63 Some(tr) => { 63 Some(tr) => {
64 res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); 64 res.impls_by_trait.entry(tr.value.trait_).or_default().push(impl_id);
65 } 65 }
66 None => { 66 None => {
67 let self_ty = db.impl_self_ty(impl_id); 67 let self_ty = db.impl_self_ty(impl_id);
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index 446d12813..1722563aa 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -697,7 +697,7 @@ fn test<U, T: Trait<U>>(t: T) {
697 [71; 72) 't': T 697 [71; 72) 't': T
698 [77; 96) '{ ...d(); }': () 698 [77; 96) '{ ...d(); }': ()
699 [83; 84) 't': T 699 [83; 84) 't': T
700 [83; 93) 't.method()': [missing name] 700 [83; 93) 't.method()': U
701 "### 701 "###
702 ); 702 );
703} 703}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index dc78e83cd..e6f697fa3 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -822,8 +822,7 @@ fn test<T: ApplyL>() {
822"#, 822"#,
823 ); 823 );
824 // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. 824 // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
825 // FIXME: fix type parameter names going missing when going through Chalk 825 assert_eq!(t, "ApplyL::Out<T>");
826 assert_eq!(t, "ApplyL::Out<[missing name]>");
827} 826}
828 827
829#[test] 828#[test]
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index fe9cb556c..6e97f7dd2 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -142,8 +142,9 @@ impl ToChalk for Ty {
142 let substitution = proj_ty.parameters.to_chalk(db); 142 let substitution = proj_ty.parameters.to_chalk(db);
143 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern() 143 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern()
144 } 144 }
145 Ty::Param { idx, .. } => { 145 Ty::Param(id) => {
146 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize } 146 let interned_id = db.intern_type_param_id(id);
147 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: interned_id.as_intern_id().as_usize() }
147 .to_ty::<TypeFamily>() 148 .to_ty::<TypeFamily>()
148 } 149 }
149 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), 150 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(),
@@ -177,7 +178,8 @@ impl ToChalk for Ty {
177 }, 178 },
178 chalk_ir::TyData::Placeholder(idx) => { 179 chalk_ir::TyData::Placeholder(idx) => {
179 assert_eq!(idx.ui, UniverseIndex::ROOT); 180 assert_eq!(idx.ui, UniverseIndex::ROOT);
180 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } 181 let interned_id = crate::db::GlobalTypeParamId::from_intern_id(crate::salsa::InternId::from(idx.idx));
182 Ty::Param(db.lookup_intern_type_param_id(interned_id))
181 } 183 }
182 chalk_ir::TyData::Alias(proj) => { 184 chalk_ir::TyData::Alias(proj) => {
183 let associated_ty = from_chalk(db, proj.associated_ty_id); 185 let associated_ty = from_chalk(db, proj.associated_ty_id);
@@ -524,7 +526,7 @@ fn convert_where_clauses(
524 // skip errored predicates completely 526 // skip errored predicates completely
525 continue; 527 continue;
526 } 528 }
527 result.push(pred.clone().subst(substs).to_chalk(db)); 529 result.push(pred.clone().subst_type_params(db, def, substs).to_chalk(db));
528 } 530 }
529 result 531 result
530} 532}
@@ -709,12 +711,12 @@ fn impl_block_datum(
709 let trait_ref = db 711 let trait_ref = db
710 .impl_trait(impl_id) 712 .impl_trait(impl_id)
711 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk 713 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
712 .expect("invalid impl passed to Chalk"); 714 .expect("invalid impl passed to Chalk")
715 .value;
713 let impl_data = db.impl_data(impl_id); 716 let impl_data = db.impl_data(impl_id);
714 717
715 let generic_params = generics(db, impl_id.into()); 718 let generic_params = generics(db, impl_id.into());
716 let bound_vars = Substs::bound_vars(&generic_params); 719 let bound_vars = Substs::bound_vars(&generic_params);
717 let trait_ref = trait_ref.subst(&bound_vars);
718 let trait_ = trait_ref.trait_; 720 let trait_ = trait_ref.trait_;
719 let impl_type = if impl_id.lookup(db).container.module(db).krate == krate { 721 let impl_type = if impl_id.lookup(db).container.module(db).krate == krate {
720 chalk_rust_ir::ImplType::Local 722 chalk_rust_ir::ImplType::Local
@@ -789,20 +791,18 @@ fn type_alias_associated_ty_value(
789 _ => panic!("assoc ty value should be in impl"), 791 _ => panic!("assoc ty value should be in impl"),
790 }; 792 };
791 793
792 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved 794 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved
793 795
794 let assoc_ty = db 796 let assoc_ty = db
795 .trait_data(trait_ref.trait_) 797 .trait_data(trait_ref.trait_)
796 .associated_type_by_name(&type_alias_data.name) 798 .associated_type_by_name(&type_alias_data.name)
797 .expect("assoc ty value should not exist"); // validated when building the impl data as well 799 .expect("assoc ty value should not exist"); // validated when building the impl data as well
798 let generic_params = generics(db, impl_id.into()); 800 let ty = db.ty(type_alias.into());
799 let bound_vars = Substs::bound_vars(&generic_params); 801 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) };
800 let ty = db.ty(type_alias.into()).subst(&bound_vars);
801 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
802 let value = chalk_rust_ir::AssociatedTyValue { 802 let value = chalk_rust_ir::AssociatedTyValue {
803 impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db), 803 impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db),
804 associated_ty_id: assoc_ty.to_chalk(db), 804 associated_ty_id: assoc_ty.to_chalk(db),
805 value: make_binders(value_bound, bound_vars.len()), 805 value: make_binders(value_bound, ty.num_binders),
806 }; 806 };
807 Arc::new(value) 807 Arc::new(value)
808} 808}
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index 77b7de729..8fa1838bd 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -99,23 +99,19 @@ pub(crate) struct Generics {
99} 99}
100 100
101impl Generics { 101impl Generics {
102 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a { 102 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
103 self.parent_generics 103 self.parent_generics
104 .as_ref() 104 .as_ref()
105 .into_iter() 105 .into_iter()
106 .flat_map(|it| it.params.types.iter()) 106 .flat_map(|it| it.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)))
107 .chain(self.params.types.iter()) 107 .chain(self.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)))
108 .enumerate()
109 .map(|(i, (_local_id, p))| (i as u32, p))
110 } 108 }
111 109
112 pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a { 110 pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
113 self.parent_generics 111 self.parent_generics
114 .as_ref() 112 .as_ref()
115 .into_iter() 113 .into_iter()
116 .flat_map(|it| it.params.types.iter()) 114 .flat_map(|it| it.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)))
117 .enumerate()
118 .map(|(i, (_local_id, p))| (i as u32, p))
119 } 115 }
120 116
121 pub(crate) fn len(&self) -> usize { 117 pub(crate) fn len(&self) -> usize {
@@ -137,16 +133,11 @@ impl Generics {
137 (self_params, list_params, impl_trait_params) 133 (self_params, list_params, impl_trait_params)
138 } 134 }
139 135
140 pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { 136 pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> {
141 self.find_param(param).0 137 Some(self.find_param(param)?.0)
142 } 138 }
143 139
144 pub(crate) fn param_name(&self, param: TypeParamId) -> Name { 140 fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> {
145 // FIXME make this return Option
146 self.find_param(param).1.name.clone().unwrap_or_else(Name::missing)
147 }
148
149 fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) {
150 if param.parent == self.def { 141 if param.parent == self.def {
151 let (idx, (_local_id, data)) = self 142 let (idx, (_local_id, data)) = self
152 .params 143 .params
@@ -156,9 +147,10 @@ impl Generics {
156 .find(|(_, (idx, _))| *idx == param.local_id) 147 .find(|(_, (idx, _))| *idx == param.local_id)
157 .unwrap(); 148 .unwrap();
158 let (_total, parent_len, _child) = self.len_split(); 149 let (_total, parent_len, _child) = self.len_split();
159 return ((parent_len + idx) as u32, data); 150 Some(((parent_len + idx) as u32, data))
151 } else {
152 self.parent_generics.as_ref().and_then(|g| g.find_param(param))
160 } 153 }
161 self.parent_generics.as_ref().unwrap().find_param(param)
162 } 154 }
163} 155}
164 156