aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model.rs14
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/ty.rs141
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs14
-rw-r--r--crates/ra_hir/src/ty/infer.rs15
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs10
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs24
-rw-r--r--crates/ra_hir/src/ty/lower.rs20
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs18
-rw-r--r--crates/ra_hir/src/ty/tests.rs1
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs80
11 files changed, 212 insertions, 126 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 20413cb3d..fd7afcbb6 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -339,10 +339,14 @@ pub struct Struct {
339} 339}
340 340
341impl Struct { 341impl Struct {
342 pub fn module(self, db: &impl HirDatabase) -> Module { 342 pub fn module(self, db: &impl DefDatabase) -> Module {
343 self.id.module(db) 343 self.id.module(db)
344 } 344 }
345 345
346 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
347 self.module(db).krate(db)
348 }
349
346 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 350 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
347 db.struct_data(self).name.clone() 351 db.struct_data(self).name.clone()
348 } 352 }
@@ -423,10 +427,14 @@ pub struct Enum {
423} 427}
424 428
425impl Enum { 429impl Enum {
426 pub fn module(self, db: &impl HirDatabase) -> Module { 430 pub fn module(self, db: &impl DefDatabase) -> Module {
427 self.id.module(db) 431 self.id.module(db)
428 } 432 }
429 433
434 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
435 self.module(db).krate(db)
436 }
437
430 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 438 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
431 db.enum_data(self).name.clone() 439 db.enum_data(self).name.clone()
432 } 440 }
@@ -514,7 +522,7 @@ impl Adt {
514 } 522 }
515 } 523 }
516 524
517 pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> { 525 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
518 match self { 526 match self {
519 Adt::Struct(s) => s.module(db), 527 Adt::Struct(s) => s.module(db),
520 Adt::Union(s) => s.module(db), 528 Adt::Union(s) => s.module(db),
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index b2111be05..125e0beea 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -9,7 +9,6 @@ test_utils::marks!(
9 glob_across_crates 9 glob_across_crates
10 std_prelude 10 std_prelude
11 match_ergonomics_ref 11 match_ergonomics_ref
12 trait_resolution_on_fn_type
13 infer_while_let 12 infer_while_let
14 macro_rules_from_other_crates_are_visible_with_macro_use 13 macro_rules_from_other_crates_are_visible_with_macro_use
15 prelude_is_macro_use 14 prelude_is_macro_use
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index fae9c1e22..d161735e8 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -14,11 +14,11 @@ pub(crate) mod display;
14 14
15use std::ops::Deref; 15use std::ops::Deref;
16use std::sync::Arc; 16use std::sync::Arc;
17use std::{fmt, mem}; 17use std::{fmt, iter, mem};
18 18
19use crate::{ 19use crate::{
20 db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, DefWithBody, GenericParams, Name, 20 db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, Crate, DefWithBody, GenericParams,
21 Trait, TypeAlias, 21 HasGenericParams, Name, Trait, TypeAlias,
22}; 22};
23use display::{HirDisplay, HirFormatter}; 23use display::{HirDisplay, HirFormatter};
24 24
@@ -111,6 +111,81 @@ pub enum TypeCtor {
111 Closure { def: DefWithBody, expr: ExprId }, 111 Closure { def: DefWithBody, expr: ExprId },
112} 112}
113 113
114impl TypeCtor {
115 pub fn num_ty_params(self, db: &impl HirDatabase) -> usize {
116 match self {
117 TypeCtor::Bool
118 | TypeCtor::Char
119 | TypeCtor::Int(_)
120 | TypeCtor::Float(_)
121 | TypeCtor::Str
122 | TypeCtor::Never => 0,
123 TypeCtor::Slice
124 | TypeCtor::Array
125 | TypeCtor::RawPtr(_)
126 | TypeCtor::Ref(_)
127 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure
128 => 1,
129 TypeCtor::Adt(adt) => {
130 let generic_params = adt.generic_params(db);
131 generic_params.count_params_including_parent()
132 }
133 TypeCtor::FnDef(callable) => {
134 let generic_params = callable.generic_params(db);
135 generic_params.count_params_including_parent()
136 }
137 TypeCtor::AssociatedType(type_alias) => {
138 let generic_params = type_alias.generic_params(db);
139 generic_params.count_params_including_parent()
140 }
141 TypeCtor::FnPtr { num_args } => num_args as usize + 1,
142 TypeCtor::Tuple { cardinality } => cardinality as usize,
143 }
144 }
145
146 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
147 match self {
148 TypeCtor::Bool
149 | TypeCtor::Char
150 | TypeCtor::Int(_)
151 | TypeCtor::Float(_)
152 | TypeCtor::Str
153 | TypeCtor::Never
154 | TypeCtor::Slice
155 | TypeCtor::Array
156 | TypeCtor::RawPtr(_)
157 | TypeCtor::Ref(_)
158 | TypeCtor::FnPtr { .. }
159 | TypeCtor::Tuple { .. } => None,
160 TypeCtor::Closure { def, .. } => def.krate(db),
161 TypeCtor::Adt(adt) => adt.krate(db),
162 TypeCtor::FnDef(callable) => callable.krate(db),
163 TypeCtor::AssociatedType(type_alias) => type_alias.krate(db),
164 }
165 }
166
167 pub fn as_generic_def(self) -> Option<crate::generics::GenericDef> {
168 match self {
169 TypeCtor::Bool
170 | TypeCtor::Char
171 | TypeCtor::Int(_)
172 | TypeCtor::Float(_)
173 | TypeCtor::Str
174 | TypeCtor::Never
175 | TypeCtor::Slice
176 | TypeCtor::Array
177 | TypeCtor::RawPtr(_)
178 | TypeCtor::Ref(_)
179 | TypeCtor::FnPtr { .. }
180 | TypeCtor::Tuple { .. }
181 | TypeCtor::Closure { .. } => None,
182 TypeCtor::Adt(adt) => Some(adt.into()),
183 TypeCtor::FnDef(callable) => Some(callable.into()),
184 TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()),
185 }
186 }
187}
188
114/// A nominal type with (maybe 0) type parameters. This might be a primitive 189/// A nominal type with (maybe 0) type parameters. This might be a primitive
115/// type like `bool`, a struct, tuple, function pointer, reference or 190/// type like `bool`, a struct, tuple, function pointer, reference or
116/// several other things. 191/// several other things.
@@ -271,11 +346,65 @@ impl Substs {
271 .into(), 346 .into(),
272 ) 347 )
273 } 348 }
349
350 pub fn build_for_def(
351 db: &impl HirDatabase,
352 def: impl crate::HasGenericParams,
353 ) -> SubstsBuilder {
354 let params = def.generic_params(db);
355 let param_count = params.count_params_including_parent();
356 Substs::builder(param_count)
357 }
358
359 pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder {
360 Substs::builder(generic_params.count_params_including_parent())
361 }
362
363 pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
364 Substs::builder(type_ctor.num_ty_params(db))
365 }
366
367 fn builder(param_count: usize) -> SubstsBuilder {
368 SubstsBuilder { vec: Vec::with_capacity(param_count), param_count }
369 }
370}
371
372#[derive(Debug, Clone)]
373pub struct SubstsBuilder {
374 vec: Vec<Ty>,
375 param_count: usize,
274} 376}
275 377
276impl From<Vec<Ty>> for Substs { 378impl SubstsBuilder {
277 fn from(v: Vec<Ty>) -> Self { 379 pub fn build(self) -> Substs {
278 Substs(v.into()) 380 assert_eq!(self.vec.len(), self.param_count);
381 Substs(self.vec.into())
382 }
383
384 pub fn push(mut self, ty: Ty) -> Self {
385 self.vec.push(ty);
386 self
387 }
388
389 fn remaining(&self) -> usize {
390 self.param_count - self.vec.len()
391 }
392
393 pub fn fill_with_bound_vars(mut self, starting_from: u32) -> Self {
394 self.vec.extend((starting_from..starting_from + self.remaining() as u32).map(Ty::Bound));
395 self
396 }
397
398 pub fn fill_with_unknown(mut self) -> Self {
399 self.vec.extend(iter::repeat(Ty::Unknown).take(self.remaining()));
400 self
401 }
402
403 pub fn use_parent_substs(mut self, parent_substs: &Substs) -> Self {
404 assert!(self.vec.is_empty());
405 assert!(parent_substs.len() <= self.param_count);
406 self.vec.extend(parent_substs.iter().cloned());
407 self
279 } 408 }
280} 409}
281 410
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 94f8ecdc9..02492ca14 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -7,7 +7,7 @@ use std::iter::successors;
7 7
8use log::{info, warn}; 8use log::{info, warn};
9 9
10use super::{traits::Solution, Canonical, Ty, TypeWalk}; 10use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
11use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; 11use crate::{db::HirDatabase, name, HasGenericParams, Resolver};
12 12
13const AUTODEREF_RECURSION_LIMIT: usize = 10; 13const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -44,7 +44,8 @@ fn deref_by_trait(
44 }; 44 };
45 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; 45 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?;
46 46
47 if target.generic_params(db).count_params_including_parent() != 1 { 47 let generic_params = target.generic_params(db);
48 if generic_params.count_params_including_parent() != 1 {
48 // the Target type + Deref trait should only have one generic parameter, 49 // the Target type + Deref trait should only have one generic parameter,
49 // namely Deref's Self type 50 // namely Deref's Self type
50 return None; 51 return None;
@@ -54,12 +55,13 @@ fn deref_by_trait(
54 55
55 let env = super::lower::trait_env(db, resolver); 56 let env = super::lower::trait_env(db, resolver);
56 57
58 let parameters = Substs::build_for_generics(&generic_params)
59 .push(ty.value.clone().shift_bound_vars(1))
60 .build();
61
57 let projection = super::traits::ProjectionPredicate { 62 let projection = super::traits::ProjectionPredicate {
58 ty: Ty::Bound(0), 63 ty: Ty::Bound(0),
59 projection_ty: super::ProjectionTy { 64 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
60 associated_ty: target,
61 parameters: vec![ty.value.clone().shift_bound_vars(1)].into(),
62 },
63 }; 65 };
64 66
65 let obligation = super::Obligation::Projection(projection); 67 let obligation = super::Obligation::Projection(projection);
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index db3377357..8e07fc186 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -688,14 +688,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
688 }; 688 };
689 let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); 689 let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
690 690
691 let inner_tys: Substs = args 691 let inner_tys = args
692 .iter() 692 .iter()
693 .zip(expectations_iter) 693 .zip(expectations_iter)
694 .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm)) 694 .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm))
695 .collect::<Vec<_>>() 695 .collect();
696 .into();
697 696
698 Ty::apply(TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, inner_tys) 697 Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys))
699 } 698 }
700 Pat::Ref { pat, mutability } => { 699 Pat::Ref { pat, mutability } => {
701 let expectation = match expected.as_reference() { 700 let expectation = match expected.as_reference() {
@@ -1229,7 +1228,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1229 ty: pat_ty.clone(), 1228 ty: pat_ty.clone(),
1230 projection_ty: ProjectionTy { 1229 projection_ty: ProjectionTy {
1231 associated_ty: into_iter_item_alias, 1230 associated_ty: into_iter_item_alias,
1232 parameters: vec![iterable_ty].into(), 1231 parameters: Substs::single(iterable_ty),
1233 }, 1232 },
1234 }; 1233 };
1235 self.obligations.push(Obligation::Projection(projection)); 1234 self.obligations.push(Obligation::Projection(projection));
@@ -1262,7 +1261,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1262 sig_tys.push(ret_ty.clone()); 1261 sig_tys.push(ret_ty.clone());
1263 let sig_ty = Ty::apply( 1262 let sig_ty = Ty::apply(
1264 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 1263 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
1265 sig_tys.into(), 1264 Substs(sig_tys.into()),
1266 ); 1265 );
1267 let closure_ty = Ty::apply_one( 1266 let closure_ty = Ty::apply_one(
1268 TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr }, 1267 TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr },
@@ -1400,7 +1399,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1400 ty: ty.clone(), 1399 ty: ty.clone(),
1401 projection_ty: ProjectionTy { 1400 projection_ty: ProjectionTy {
1402 associated_ty: future_future_output_alias, 1401 associated_ty: future_future_output_alias,
1403 parameters: vec![inner_ty].into(), 1402 parameters: Substs::single(inner_ty),
1404 }, 1403 },
1405 }; 1404 };
1406 self.obligations.push(Obligation::Projection(projection)); 1405 self.obligations.push(Obligation::Projection(projection));
@@ -1419,7 +1418,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1419 ty: ty.clone(), 1418 ty: ty.clone(),
1420 projection_ty: ProjectionTy { 1419 projection_ty: ProjectionTy {
1421 associated_ty: ops_try_ok_alias, 1420 associated_ty: ops_try_ok_alias,
1422 parameters: vec![inner_ty].into(), 1421 parameters: Substs::single(inner_ty),
1423 }, 1422 },
1424 }; 1423 };
1425 self.obligations.push(Obligation::Projection(projection)); 1424 self.obligations.push(Obligation::Projection(projection));
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index feb7481b2..db979353a 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -158,13 +158,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
158 AssocItem::Const(c) => ValueNs::Const(c), 158 AssocItem::Const(c) => ValueNs::Const(c),
159 AssocItem::TypeAlias(_) => unreachable!(), 159 AssocItem::TypeAlias(_) => unreachable!(),
160 }; 160 };
161 let generics = item.generic_params(self.db); 161 let substs = Substs::build_for_def(self.db, item)
162 let mut substs = Vec::with_capacity(generics.count_params_including_parent()); 162 .use_parent_substs(&trait_ref.substs)
163 substs.extend(trait_ref.substs.iter().cloned()); 163 .fill_with_unknown()
164 substs.extend(std::iter::repeat(Ty::Unknown).take(generics.params.len())); 164 .build();
165 165
166 self.write_assoc_resolution(id, item); 166 self.write_assoc_resolution(id, item);
167 Some((def, Some(substs.into()))) 167 Some((def, Some(substs)))
168 } 168 }
169 169
170 fn resolve_ty_assoc_item( 170 fn resolve_ty_assoc_item(
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index b6ebee3b1..d161aa6b3 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -3,7 +3,8 @@
3use super::{InferenceContext, Obligation}; 3use super::{InferenceContext, Obligation};
4use crate::db::HirDatabase; 4use crate::db::HirDatabase;
5use crate::ty::{ 5use crate::ty::{
6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk, 6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty,
7 TypeWalk,
7}; 8};
8 9
9impl<'a, D: HirDatabase> InferenceContext<'a, D> { 10impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -74,12 +75,9 @@ where
74 } 75 }
75 76
76 fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef { 77 fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef {
77 let substs = trait_ref 78 let substs =
78 .substs 79 trait_ref.substs.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect();
79 .iter() 80 TraitRef { trait_: trait_ref.trait_, substs: Substs(substs) }
80 .map(|ty| self.do_canonicalize_ty(ty.clone()))
81 .collect::<Vec<_>>();
82 TraitRef { trait_: trait_ref.trait_, substs: substs.into() }
83 } 81 }
84 82
85 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 83 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
@@ -90,12 +88,9 @@ where
90 } 88 }
91 89
92 fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy { 90 fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy {
93 let params = projection_ty 91 let params =
94 .parameters 92 projection_ty.parameters.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect();
95 .iter() 93 ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: Substs(params) }
96 .map(|ty| self.do_canonicalize_ty(ty.clone()))
97 .collect::<Vec<_>>();
98 ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: params.into() }
99 } 94 }
100 95
101 fn do_canonicalize_projection_predicate( 96 fn do_canonicalize_projection_predicate(
@@ -153,8 +148,7 @@ impl<T> Canonicalized<T> {
153 solution: Canonical<Vec<Ty>>, 148 solution: Canonical<Vec<Ty>>,
154 ) { 149 ) {
155 // the solution may contain new variables, which we need to convert to new inference vars 150 // the solution may contain new variables, which we need to convert to new inference vars
156 let new_vars = 151 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect());
157 (0..solution.num_vars).map(|_| ctx.new_type_var()).collect::<Vec<_>>().into();
158 for (i, ty) in solution.value.into_iter().enumerate() { 152 for (i, ty) in solution.value.into_iter().enumerate() {
159 let var = self.free_vars[i]; 153 let var = self.free_vars[i];
160 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); 154 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars));
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index dd503d771..4b67c82e7 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -239,14 +239,10 @@ impl Ty {
239 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); 239 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db));
240 for t in traits { 240 for t in traits {
241 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { 241 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) {
242 let generics = t.generic_params(db); 242 let substs =
243 let mut substs = Vec::new(); 243 Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build();
244 substs.push(self_ty.clone());
245 substs.extend(
246 iter::repeat(Ty::Unknown).take(generics.count_params_including_parent() - 1),
247 );
248 // FIXME handle type parameters on the segment 244 // FIXME handle type parameters on the segment
249 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs.into() }); 245 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs });
250 } 246 }
251 } 247 }
252 Ty::Unknown 248 Ty::Unknown
@@ -766,6 +762,16 @@ pub enum CallableDef {
766} 762}
767impl_froms!(CallableDef: Function, Struct, EnumVariant); 763impl_froms!(CallableDef: Function, Struct, EnumVariant);
768 764
765impl CallableDef {
766 pub fn krate(self, db: &impl HirDatabase) -> Option<crate::Crate> {
767 match self {
768 CallableDef::Function(f) => f.krate(db),
769 CallableDef::Struct(s) => s.krate(db),
770 CallableDef::EnumVariant(e) => e.parent_enum(db).krate(db),
771 }
772 }
773}
774
769impl From<CallableDef> for GenericDef { 775impl From<CallableDef> for GenericDef {
770 fn from(def: CallableDef) -> GenericDef { 776 fn from(def: CallableDef) -> GenericDef {
771 match def { 777 match def {
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 4b71b376f..ad2ab560d 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -10,7 +10,6 @@ use rustc_hash::FxHashMap;
10use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 10use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
11use crate::{ 11use crate::{
12 db::HirDatabase, 12 db::HirDatabase,
13 generics::HasGenericParams,
14 impl_block::{ImplBlock, ImplId}, 13 impl_block::{ImplBlock, ImplId},
15 nameres::CrateModuleId, 14 nameres::CrateModuleId,
16 resolve::Resolver, 15 resolve::Resolver,
@@ -331,20 +330,13 @@ fn generic_implements_goal(
331 trait_: Trait, 330 trait_: Trait,
332 self_ty: Canonical<Ty>, 331 self_ty: Canonical<Ty>,
333) -> Canonical<InEnvironment<super::Obligation>> { 332) -> Canonical<InEnvironment<super::Obligation>> {
334 let mut substs = Vec::new();
335 let generics = trait_.generic_params(db);
336 let num_vars = self_ty.num_vars; 333 let num_vars = self_ty.num_vars;
337 substs.push(self_ty.value); 334 let substs = super::Substs::build_for_def(db, trait_)
338 substs.extend( 335 .push(self_ty.value)
339 generics 336 .fill_with_bound_vars(num_vars as u32)
340 .params_including_parent() 337 .build();
341 .into_iter()
342 .skip(1)
343 .enumerate()
344 .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)),
345 );
346 let num_vars = substs.len() - 1 + self_ty.num_vars; 338 let num_vars = substs.len() - 1 + self_ty.num_vars;
347 let trait_ref = TraitRef { trait_, substs: substs.into() }; 339 let trait_ref = TraitRef { trait_, substs };
348 let obligation = super::Obligation::Trait(trait_ref); 340 let obligation = super::Obligation::Trait(trait_ref);
349 Canonical { num_vars, value: InEnvironment::new(env, obligation) } 341 Canonical { num_vars, value: InEnvironment::new(env, obligation) }
350} 342}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 4362bb27a..7de434180 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3321,7 +3321,6 @@ fn test() { S2.into()<|>; }
3321 3321
3322#[test] 3322#[test]
3323fn method_resolution_encountering_fn_type() { 3323fn method_resolution_encountering_fn_type() {
3324 covers!(trait_resolution_on_fn_type);
3325 type_at( 3324 type_at(
3326 r#" 3325 r#"
3327//- /main.rs 3326//- /main.rs
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 538b4d3ec..2642a54bf 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -10,17 +10,13 @@ use chalk_ir::{
10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
11 11
12use ra_db::salsa::{InternId, InternKey}; 12use ra_db::salsa::{InternId, InternKey};
13use test_utils::tested_by;
14 13
15use super::{Canonical, ChalkContext, Impl, Obligation}; 14use super::{Canonical, ChalkContext, Impl, Obligation};
16use crate::{ 15use crate::{
17 db::HirDatabase, 16 db::HirDatabase,
18 generics::GenericDef, 17 generics::GenericDef,
19 ty::display::HirDisplay, 18 ty::display::HirDisplay,
20 ty::{ 19 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
22 TypeWalk,
23 },
24 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, 20 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias,
25}; 21};
26 22
@@ -124,14 +120,15 @@ impl ToChalk for Substs {
124 } 120 }
125 121
126 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs { 122 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs {
127 parameters 123 let tys = parameters
128 .into_iter() 124 .into_iter()
129 .map(|p| match p { 125 .map(|p| match p {
130 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), 126 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty),
131 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), 127 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(),
132 }) 128 })
133 .collect::<Vec<_>>() 129 .collect::<Vec<_>>()
134 .into() 130 .into();
131 Substs(tys)
135 } 132 }
136} 133}
137 134
@@ -539,60 +536,18 @@ pub(crate) fn struct_datum_query(
539 struct_id: chalk_ir::StructId, 536 struct_id: chalk_ir::StructId,
540) -> Arc<StructDatum> { 537) -> Arc<StructDatum> {
541 debug!("struct_datum {:?}", struct_id); 538 debug!("struct_datum {:?}", struct_id);
542 let type_ctor = from_chalk(db, struct_id); 539 let type_ctor: TypeCtor = from_chalk(db, struct_id);
543 debug!("struct {:?} = {:?}", struct_id, type_ctor); 540 debug!("struct {:?} = {:?}", struct_id, type_ctor);
544 // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor 541 let num_params = type_ctor.num_ty_params(db);
545 // FIXME extract this to a method on Ty 542 let upstream = type_ctor.krate(db) != Some(krate);
546 let (num_params, where_clauses, upstream) = match type_ctor { 543 let where_clauses = type_ctor
547 TypeCtor::Bool 544 .as_generic_def()
548 | TypeCtor::Char 545 .map(|generic_def| {
549 | TypeCtor::Int(_)
550 | TypeCtor::Float(_)
551 | TypeCtor::Never
552 | TypeCtor::Str => (0, vec![], true),
553 TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => {
554 (1, vec![], true)
555 }
556 TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true),
557 TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true),
558 TypeCtor::FnDef(callable) => {
559 tested_by!(trait_resolution_on_fn_type);
560 let upstream = match callable {
561 CallableDef::Function(f) => f.module(db).krate(db),
562 CallableDef::Struct(s) => s.module(db).krate(db),
563 CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db),
564 } != Some(krate);
565 let generic_def: GenericDef = callable.into();
566 let generic_params = generic_def.generic_params(db); 546 let generic_params = generic_def.generic_params(db);
567 let bound_vars = Substs::bound_vars(&generic_params); 547 let bound_vars = Substs::bound_vars(&generic_params);
568 let where_clauses = convert_where_clauses(db, generic_def, &bound_vars); 548 convert_where_clauses(db, generic_def, &bound_vars)
569 (generic_params.count_params_including_parent(), where_clauses, upstream) 549 })
570 } 550 .unwrap_or_else(Vec::new);
571 TypeCtor::Adt(adt) => {
572 let generic_params = adt.generic_params(db);
573 let bound_vars = Substs::bound_vars(&generic_params);
574 let where_clauses = convert_where_clauses(db, adt.into(), &bound_vars);
575 (
576 generic_params.count_params_including_parent(),
577 where_clauses,
578 adt.krate(db) != Some(krate),
579 )
580 }
581 TypeCtor::AssociatedType(type_alias) => {
582 let generic_params = type_alias.generic_params(db);
583 let bound_vars = Substs::bound_vars(&generic_params);
584 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
585 (
586 generic_params.count_params_including_parent(),
587 where_clauses,
588 type_alias.krate(db) != Some(krate),
589 )
590 }
591 TypeCtor::Closure { def, .. } => {
592 let upstream = def.krate(db) != Some(krate);
593 (1, vec![], upstream)
594 }
595 };
596 let flags = chalk_rust_ir::StructFlags { 551 let flags = chalk_rust_ir::StructFlags {
597 upstream, 552 upstream,
598 // FIXME set fundamental flag correctly 553 // FIXME set fundamental flag correctly
@@ -729,17 +684,20 @@ fn closure_fn_trait_impl_datum(
729 684
730 let arg_ty = Ty::apply( 685 let arg_ty = Ty::apply(
731 TypeCtor::Tuple { cardinality: num_args }, 686 TypeCtor::Tuple { cardinality: num_args },
732 (0..num_args).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(), 687 Substs::builder(num_args as usize).fill_with_bound_vars(0).build(),
733 ); 688 );
734 let output_ty = Ty::Bound(num_args.into()); 689 let output_ty = Ty::Bound(num_args.into());
735 let sig_ty = Ty::apply( 690 let sig_ty = Ty::apply(
736 TypeCtor::FnPtr { num_args }, 691 TypeCtor::FnPtr { num_args },
737 (0..num_args + 1).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(), 692 Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(),
738 ); 693 );
739 694
740 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); 695 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
741 696
742 let trait_ref = TraitRef { trait_, substs: vec![self_ty, arg_ty].into() }; 697 let trait_ref = TraitRef {
698 trait_,
699 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
700 };
743 701
744 let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?; 702 let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?;
745 703