diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-26 22:04:20 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-26 22:04:20 +0100 |
commit | fc218ec0d04577e33db509e956a044293c12ea67 (patch) | |
tree | 2229733948df98f119aee5eca600a50726192c68 /crates/ra_hir/src | |
parent | 1002e470747fe5887a2915689e21d9be3a1ca5d8 (diff) | |
parent | daaf46177e5dc63e20e5a1ec5692e53cc8f7bc34 (diff) |
Merge #1923
1923: Add SubstsBuilder r=flodiebold a=flodiebold
+ further refactoring.
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 141 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/path.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/unify.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 80 |
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 | ||
341 | impl Struct { | 341 | impl 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 | ||
425 | impl Enum { | 429 | impl 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 | ||
15 | use std::ops::Deref; | 15 | use std::ops::Deref; |
16 | use std::sync::Arc; | 16 | use std::sync::Arc; |
17 | use std::{fmt, mem}; | 17 | use std::{fmt, iter, mem}; |
18 | 18 | ||
19 | use crate::{ | 19 | use 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 | }; |
23 | use display::{HirDisplay, HirFormatter}; | 23 | use 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 | ||
114 | impl 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)] | ||
373 | pub struct SubstsBuilder { | ||
374 | vec: Vec<Ty>, | ||
375 | param_count: usize, | ||
274 | } | 376 | } |
275 | 377 | ||
276 | impl From<Vec<Ty>> for Substs { | 378 | impl 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 | ||
8 | use log::{info, warn}; | 8 | use log::{info, warn}; |
9 | 9 | ||
10 | use super::{traits::Solution, Canonical, Ty, TypeWalk}; | 10 | use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; |
11 | use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; | 11 | use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; |
12 | 12 | ||
13 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 13 | const 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 @@ | |||
3 | use super::{InferenceContext, Obligation}; | 3 | use super::{InferenceContext, Obligation}; |
4 | use crate::db::HirDatabase; | 4 | use crate::db::HirDatabase; |
5 | use crate::ty::{ | 5 | use 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 | ||
9 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 10 | impl<'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 | } |
767 | impl_froms!(CallableDef: Function, Struct, EnumVariant); | 763 | impl_froms!(CallableDef: Function, Struct, EnumVariant); |
768 | 764 | ||
765 | impl 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 | |||
769 | impl From<CallableDef> for GenericDef { | 775 | impl 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; | |||
10 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 10 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; |
11 | use crate::{ | 11 | use 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] |
3323 | fn method_resolution_encountering_fn_type() { | 3323 | fn 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::{ | |||
10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use ra_db::salsa::{InternId, InternKey}; | 12 | use ra_db::salsa::{InternId, InternKey}; |
13 | use test_utils::tested_by; | ||
14 | 13 | ||
15 | use super::{Canonical, ChalkContext, Impl, Obligation}; | 14 | use super::{Canonical, ChalkContext, Impl, Obligation}; |
16 | use crate::{ | 15 | use 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 | ||