diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 52 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/coerce.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/expr.rs | 81 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/pat.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/path.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 150 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 68 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 40 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 48 |
11 files changed, 315 insertions, 214 deletions
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 5d8518041..44547197c 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -5,48 +5,56 @@ | |||
5 | 5 | ||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use hir_def::resolver::Resolver; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | use hir_expand::name; | 9 | use hir_expand::name; |
10 | use log::{info, warn}; | 10 | use log::{info, warn}; |
11 | use ra_db::CrateId; | ||
11 | 12 | ||
12 | use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; | 13 | use crate::{db::HirDatabase, Trait}; |
13 | use crate::{db::HirDatabase, generics::HasGenericParams}; | 14 | |
15 | use super::{ | ||
16 | traits::{InEnvironment, Solution}, | ||
17 | Canonical, Substs, Ty, TypeWalk, | ||
18 | }; | ||
14 | 19 | ||
15 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 20 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
16 | 21 | ||
17 | pub(crate) fn autoderef<'a>( | 22 | pub(crate) fn autoderef<'a>( |
18 | db: &'a impl HirDatabase, | 23 | db: &'a impl HirDatabase, |
19 | resolver: &'a Resolver, | 24 | krate: Option<CrateId>, |
20 | ty: Canonical<Ty>, | 25 | ty: InEnvironment<Canonical<Ty>>, |
21 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { | 26 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { |
22 | successors(Some(ty), move |ty| deref(db, resolver, ty)).take(AUTODEREF_RECURSION_LIMIT) | 27 | let InEnvironment { value: ty, environment } = ty; |
28 | successors(Some(ty), move |ty| { | ||
29 | deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) | ||
30 | }) | ||
31 | .take(AUTODEREF_RECURSION_LIMIT) | ||
23 | } | 32 | } |
24 | 33 | ||
25 | pub(crate) fn deref( | 34 | pub(crate) fn deref( |
26 | db: &impl HirDatabase, | 35 | db: &impl HirDatabase, |
27 | resolver: &Resolver, | 36 | krate: CrateId, |
28 | ty: &Canonical<Ty>, | 37 | ty: InEnvironment<&Canonical<Ty>>, |
29 | ) -> Option<Canonical<Ty>> { | 38 | ) -> Option<Canonical<Ty>> { |
30 | if let Some(derefed) = ty.value.builtin_deref() { | 39 | if let Some(derefed) = ty.value.value.builtin_deref() { |
31 | Some(Canonical { value: derefed, num_vars: ty.num_vars }) | 40 | Some(Canonical { value: derefed, num_vars: ty.value.num_vars }) |
32 | } else { | 41 | } else { |
33 | deref_by_trait(db, resolver, ty) | 42 | deref_by_trait(db, krate, ty) |
34 | } | 43 | } |
35 | } | 44 | } |
36 | 45 | ||
37 | fn deref_by_trait( | 46 | fn deref_by_trait( |
38 | db: &impl HirDatabase, | 47 | db: &impl HirDatabase, |
39 | resolver: &Resolver, | 48 | krate: CrateId, |
40 | ty: &Canonical<Ty>, | 49 | ty: InEnvironment<&Canonical<Ty>>, |
41 | ) -> Option<Canonical<Ty>> { | 50 | ) -> Option<Canonical<Ty>> { |
42 | let krate = resolver.krate()?; | ||
43 | let deref_trait = match db.lang_item(krate.into(), "deref".into())? { | 51 | let deref_trait = match db.lang_item(krate.into(), "deref".into())? { |
44 | crate::lang_item::LangItemTarget::Trait(t) => t, | 52 | LangItemTarget::TraitId(t) => Trait::from(t), |
45 | _ => return None, | 53 | _ => return None, |
46 | }; | 54 | }; |
47 | let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; | 55 | let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; |
48 | 56 | ||
49 | let generic_params = target.generic_params(db); | 57 | let generic_params = db.generic_params(target.id.into()); |
50 | if generic_params.count_params_including_parent() != 1 { | 58 | if generic_params.count_params_including_parent() != 1 { |
51 | // the Target type + Deref trait should only have one generic parameter, | 59 | // the Target type + Deref trait should only have one generic parameter, |
52 | // namely Deref's Self type | 60 | // namely Deref's Self type |
@@ -55,10 +63,8 @@ fn deref_by_trait( | |||
55 | 63 | ||
56 | // FIXME make the Canonical handling nicer | 64 | // FIXME make the Canonical handling nicer |
57 | 65 | ||
58 | let env = super::lower::trait_env(db, resolver); | ||
59 | |||
60 | let parameters = Substs::build_for_generics(&generic_params) | 66 | let parameters = Substs::build_for_generics(&generic_params) |
61 | .push(ty.value.clone().shift_bound_vars(1)) | 67 | .push(ty.value.value.clone().shift_bound_vars(1)) |
62 | .build(); | 68 | .build(); |
63 | 69 | ||
64 | let projection = super::traits::ProjectionPredicate { | 70 | let projection = super::traits::ProjectionPredicate { |
@@ -68,9 +74,9 @@ fn deref_by_trait( | |||
68 | 74 | ||
69 | let obligation = super::Obligation::Projection(projection); | 75 | let obligation = super::Obligation::Projection(projection); |
70 | 76 | ||
71 | let in_env = super::traits::InEnvironment { value: obligation, environment: env }; | 77 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; |
72 | 78 | ||
73 | let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env }; | 79 | let canonical = super::Canonical { num_vars: 1 + ty.value.num_vars, value: in_env }; |
74 | 80 | ||
75 | let solution = db.trait_solve(krate.into(), canonical)?; | 81 | let solution = db.trait_solve(krate.into(), canonical)?; |
76 | 82 | ||
@@ -88,14 +94,14 @@ fn deref_by_trait( | |||
88 | // the case. | 94 | // the case. |
89 | for i in 1..vars.0.num_vars { | 95 | for i in 1..vars.0.num_vars { |
90 | if vars.0.value[i] != Ty::Bound((i - 1) as u32) { | 96 | if vars.0.value[i] != Ty::Bound((i - 1) as u32) { |
91 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty, solution); | 97 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); |
92 | return None; | 98 | return None; |
93 | } | 99 | } |
94 | } | 100 | } |
95 | Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) | 101 | Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) |
96 | } | 102 | } |
97 | Solution::Ambig(_) => { | 103 | Solution::Ambig(_) => { |
98 | info!("Ambiguous solution for derefing {:?}: {:?}", ty, solution); | 104 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); |
99 | None | 105 | None |
100 | } | 106 | } |
101 | } | 107 | } |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 69b13baef..6fd00d457 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -22,6 +22,7 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | |||
22 | use rustc_hash::FxHashMap; | 22 | use rustc_hash::FxHashMap; |
23 | 23 | ||
24 | use hir_def::{ | 24 | use hir_def::{ |
25 | data::{ConstData, FunctionData}, | ||
25 | path::known, | 26 | path::known, |
26 | resolver::{HasResolver, Resolver, TypeNs}, | 27 | resolver::{HasResolver, Resolver, TypeNs}, |
27 | type_ref::{Mutability, TypeRef}, | 28 | type_ref::{Mutability, TypeRef}, |
@@ -33,7 +34,6 @@ use ra_prof::profile; | |||
33 | use test_utils::tested_by; | 34 | use test_utils::tested_by; |
34 | 35 | ||
35 | use super::{ | 36 | use super::{ |
36 | lower, | ||
37 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 37 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, |
38 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, | 38 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, |
39 | TypeCtor, TypeWalk, Uncertain, | 39 | TypeCtor, TypeWalk, Uncertain, |
@@ -43,8 +43,7 @@ use crate::{ | |||
43 | db::HirDatabase, | 43 | db::HirDatabase, |
44 | expr::{BindingAnnotation, Body, ExprId, PatId}, | 44 | expr::{BindingAnnotation, Body, ExprId, PatId}, |
45 | ty::infer::diagnostics::InferenceDiagnostic, | 45 | ty::infer::diagnostics::InferenceDiagnostic, |
46 | Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, | 46 | Adt, AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, Trait, VariantDef, |
47 | StructField, Trait, VariantDef, | ||
48 | }; | 47 | }; |
49 | 48 | ||
50 | macro_rules! ty_app { | 49 | macro_rules! ty_app { |
@@ -68,10 +67,10 @@ pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResu | |||
68 | let resolver = DefWithBodyId::from(def).resolver(db); | 67 | let resolver = DefWithBodyId::from(def).resolver(db); |
69 | let mut ctx = InferenceContext::new(db, def, resolver); | 68 | let mut ctx = InferenceContext::new(db, def, resolver); |
70 | 69 | ||
71 | match def { | 70 | match &def { |
72 | DefWithBody::Const(ref c) => ctx.collect_const(&c.data(db)), | 71 | DefWithBody::Const(c) => ctx.collect_const(&db.const_data(c.id)), |
73 | DefWithBody::Function(ref f) => ctx.collect_fn(&f.data(db)), | 72 | DefWithBody::Function(f) => ctx.collect_fn(&db.function_data(f.id)), |
74 | DefWithBody::Static(ref s) => ctx.collect_const(&s.data(db)), | 73 | DefWithBody::Static(s) => ctx.collect_const(&db.static_data(s.id)), |
75 | } | 74 | } |
76 | 75 | ||
77 | ctx.infer_body(); | 76 | ctx.infer_body(); |
@@ -125,6 +124,8 @@ pub struct InferenceResult { | |||
125 | method_resolutions: FxHashMap<ExprId, Function>, | 124 | method_resolutions: FxHashMap<ExprId, Function>, |
126 | /// For each field access expr, records the field it resolves to. | 125 | /// For each field access expr, records the field it resolves to. |
127 | field_resolutions: FxHashMap<ExprId, StructField>, | 126 | field_resolutions: FxHashMap<ExprId, StructField>, |
127 | /// For each field in record literal, records the field it resolves to. | ||
128 | record_field_resolutions: FxHashMap<ExprId, StructField>, | ||
128 | /// For each struct literal, records the variant it resolves to. | 129 | /// For each struct literal, records the variant it resolves to. |
129 | variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, | 130 | variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, |
130 | /// For each associated item record what it resolves to | 131 | /// For each associated item record what it resolves to |
@@ -142,6 +143,9 @@ impl InferenceResult { | |||
142 | pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { | 143 | pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { |
143 | self.field_resolutions.get(&expr).copied() | 144 | self.field_resolutions.get(&expr).copied() |
144 | } | 145 | } |
146 | pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructField> { | ||
147 | self.record_field_resolutions.get(&expr).copied() | ||
148 | } | ||
145 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantDef> { | 149 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantDef> { |
146 | self.variant_resolutions.get(&id.into()).copied() | 150 | self.variant_resolutions.get(&id.into()).copied() |
147 | } | 151 | } |
@@ -211,11 +215,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
211 | var_unification_table: InPlaceUnificationTable::new(), | 215 | var_unification_table: InPlaceUnificationTable::new(), |
212 | obligations: Vec::default(), | 216 | obligations: Vec::default(), |
213 | return_ty: Ty::Unknown, // set in collect_fn_signature | 217 | return_ty: Ty::Unknown, // set in collect_fn_signature |
214 | trait_env: lower::trait_env(db, &resolver), | 218 | trait_env: TraitEnvironment::lower(db, &resolver), |
215 | coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), | 219 | coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), |
216 | db, | 220 | db, |
217 | owner, | 221 | owner, |
218 | body: owner.body(db), | 222 | body: db.body(owner.into()), |
219 | resolver, | 223 | resolver, |
220 | } | 224 | } |
221 | } | 225 | } |
@@ -559,21 +563,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
559 | } | 563 | } |
560 | 564 | ||
561 | fn collect_const(&mut self, data: &ConstData) { | 565 | fn collect_const(&mut self, data: &ConstData) { |
562 | self.return_ty = self.make_ty(data.type_ref()); | 566 | self.return_ty = self.make_ty(&data.type_ref); |
563 | } | 567 | } |
564 | 568 | ||
565 | fn collect_fn(&mut self, data: &FnData) { | 569 | fn collect_fn(&mut self, data: &FunctionData) { |
566 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 570 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
567 | for (type_ref, pat) in data.params().iter().zip(body.params()) { | 571 | for (type_ref, pat) in data.params.iter().zip(body.params.iter()) { |
568 | let ty = self.make_ty(type_ref); | 572 | let ty = self.make_ty(type_ref); |
569 | 573 | ||
570 | self.infer_pat(*pat, &ty, BindingMode::default()); | 574 | self.infer_pat(*pat, &ty, BindingMode::default()); |
571 | } | 575 | } |
572 | self.return_ty = self.make_ty(data.ret_type()); | 576 | self.return_ty = self.make_ty(&data.ret_type); |
573 | } | 577 | } |
574 | 578 | ||
575 | fn infer_body(&mut self) { | 579 | fn infer_body(&mut self) { |
576 | self.infer_expr(self.body.body_expr(), &Expectation::has_type(self.return_ty.clone())); | 580 | self.infer_expr(self.body.body_expr, &Expectation::has_type(self.return_ty.clone())); |
577 | } | 581 | } |
578 | 582 | ||
579 | fn resolve_into_iter_item(&self) -> Option<TypeAlias> { | 583 | fn resolve_into_iter_item(&self) -> Option<TypeAlias> { |
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 0772b9df5..4b53bba73 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs | |||
@@ -4,18 +4,17 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use hir_def::resolver::Resolver; | 7 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | use test_utils::tested_by; | 9 | use test_utils::tested_by; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | db::HirDatabase, | 12 | db::HirDatabase, |
13 | lang_item::LangItemTarget, | ||
14 | ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, | 13 | ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, |
15 | Adt, Mutability, | 14 | Adt, Mutability, |
16 | }; | 15 | }; |
17 | 16 | ||
18 | use super::{InferTy, InferenceContext, TypeVarValue}; | 17 | use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; |
19 | 18 | ||
20 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 19 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
21 | /// Unify two types, but may coerce the first one to the second one | 20 | /// Unify two types, but may coerce the first one to the second one |
@@ -50,7 +49,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
50 | ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { | 49 | ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { |
51 | let krate = resolver.krate().unwrap(); | 50 | let krate = resolver.krate().unwrap(); |
52 | let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { | 51 | let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { |
53 | Some(LangItemTarget::Trait(trait_)) => db.impls_for_trait(krate.into(), trait_), | 52 | Some(LangItemTarget::TraitId(trait_)) => { |
53 | db.impls_for_trait(krate.into(), trait_.into()) | ||
54 | } | ||
54 | _ => return FxHashMap::default(), | 55 | _ => return FxHashMap::default(), |
55 | }; | 56 | }; |
56 | 57 | ||
@@ -244,14 +245,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
244 | ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), | 245 | ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), |
245 | ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), | 246 | ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), |
246 | ) if struct1 == struct2 => { | 247 | ) if struct1 == struct2 => { |
247 | let fields = struct1.fields(self.db); | 248 | let field_tys = self.db.field_types(struct1.id.into()); |
248 | let (last_field, prev_fields) = fields.split_last()?; | 249 | let struct_data = self.db.struct_data(struct1.id.0); |
250 | |||
251 | let mut fields = struct_data.variant_data.fields().iter(); | ||
252 | let (last_field_id, _data) = fields.next_back()?; | ||
249 | 253 | ||
250 | // Get the generic parameter involved in the last field. | 254 | // Get the generic parameter involved in the last field. |
251 | let unsize_generic_index = { | 255 | let unsize_generic_index = { |
252 | let mut index = None; | 256 | let mut index = None; |
253 | let mut multiple_param = false; | 257 | let mut multiple_param = false; |
254 | last_field.ty(self.db).walk(&mut |ty| match ty { | 258 | field_tys[last_field_id].walk(&mut |ty| match ty { |
255 | &Ty::Param { idx, .. } => { | 259 | &Ty::Param { idx, .. } => { |
256 | if index.is_none() { | 260 | if index.is_none() { |
257 | index = Some(idx); | 261 | index = Some(idx); |
@@ -270,8 +274,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
270 | 274 | ||
271 | // Check other fields do not involve it. | 275 | // Check other fields do not involve it. |
272 | let mut multiple_used = false; | 276 | let mut multiple_used = false; |
273 | prev_fields.iter().for_each(|field| { | 277 | fields.for_each(|(field_id, _data)| { |
274 | field.ty(self.db).walk(&mut |ty| match ty { | 278 | field_tys[field_id].walk(&mut |ty| match ty { |
275 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { | 279 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { |
276 | multiple_used = true | 280 | multiple_used = true |
277 | } | 281 | } |
@@ -316,9 +320,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
316 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); | 320 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); |
317 | let to_ty = self.resolve_ty_shallow(&to_ty); | 321 | let to_ty = self.resolve_ty_shallow(&to_ty); |
318 | // FIXME: Auto DerefMut | 322 | // FIXME: Auto DerefMut |
319 | for derefed_ty in | 323 | for derefed_ty in autoderef::autoderef( |
320 | autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) | 324 | self.db, |
321 | { | 325 | self.resolver.krate(), |
326 | InEnvironment { | ||
327 | value: canonicalized.value.clone(), | ||
328 | environment: self.trait_env.clone(), | ||
329 | }, | ||
330 | ) { | ||
322 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 331 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
323 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { | 332 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { |
324 | // Stop when constructor matches. | 333 | // Stop when constructor matches. |
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index ac570075f..194e55819 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs | |||
@@ -5,6 +5,7 @@ use std::sync::Arc; | |||
5 | 5 | ||
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | builtin_type::Signedness, | 7 | builtin_type::Signedness, |
8 | generics::GenericParams, | ||
8 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
9 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
10 | }; | 11 | }; |
@@ -13,11 +14,10 @@ use hir_expand::name; | |||
13 | use crate::{ | 14 | use crate::{ |
14 | db::HirDatabase, | 15 | db::HirDatabase, |
15 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 16 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
16 | generics::{GenericParams, HasGenericParams}, | ||
17 | ty::{ | 17 | ty::{ |
18 | autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace, | 18 | autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, |
19 | Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 19 | Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, |
20 | Uncertain, | 20 | TypeCtor, TypeWalk, Uncertain, |
21 | }, | 21 | }, |
22 | Adt, Name, | 22 | Adt, Name, |
23 | }; | 23 | }; |
@@ -214,19 +214,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
214 | self.unify(&ty, &expected.ty); | 214 | self.unify(&ty, &expected.ty); |
215 | 215 | ||
216 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 216 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
217 | let field_types = | ||
218 | def_id.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | ||
217 | for (field_idx, field) in fields.iter().enumerate() { | 219 | for (field_idx, field) in fields.iter().enumerate() { |
218 | let field_ty = def_id | 220 | let field_def = def_id.and_then(|it| match it.field(self.db, &field.name) { |
219 | .and_then(|it| match it.field(self.db, &field.name) { | 221 | Some(field) => Some(field), |
220 | Some(field) => Some(field), | 222 | None => { |
221 | None => { | 223 | self.push_diagnostic(InferenceDiagnostic::NoSuchField { |
222 | self.push_diagnostic(InferenceDiagnostic::NoSuchField { | 224 | expr: tgt_expr, |
223 | expr: tgt_expr, | 225 | field: field_idx, |
224 | field: field_idx, | 226 | }); |
225 | }); | 227 | None |
226 | None | 228 | } |
227 | } | 229 | }); |
228 | }) | 230 | if let Some(field_def) = field_def { |
229 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 231 | self.result.record_field_resolutions.insert(field.expr, field_def); |
232 | } | ||
233 | let field_ty = field_def | ||
234 | .map_or(Ty::Unknown, |it| field_types[it.id].clone()) | ||
230 | .subst(&substs); | 235 | .subst(&substs); |
231 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); | 236 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); |
232 | } | 237 | } |
@@ -240,8 +245,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
240 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); | 245 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); |
241 | let ty = autoderef::autoderef( | 246 | let ty = autoderef::autoderef( |
242 | self.db, | 247 | self.db, |
243 | &self.resolver.clone(), | 248 | self.resolver.krate(), |
244 | canonicalized.value.clone(), | 249 | InEnvironment { |
250 | value: canonicalized.value.clone(), | ||
251 | environment: self.trait_env.clone(), | ||
252 | }, | ||
245 | ) | 253 | ) |
246 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { | 254 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { |
247 | Ty::Apply(a_ty) => match a_ty.ctor { | 255 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -250,7 +258,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
250 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), | 258 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), |
251 | TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { | 259 | TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { |
252 | self.write_field_resolution(tgt_expr, field); | 260 | self.write_field_resolution(tgt_expr, field); |
253 | field.ty(self.db).subst(&a_ty.parameters) | 261 | self.db.field_types(s.id.into())[field.id] |
262 | .clone() | ||
263 | .subst(&a_ty.parameters) | ||
254 | }), | 264 | }), |
255 | _ => None, | 265 | _ => None, |
256 | }, | 266 | }, |
@@ -330,16 +340,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
330 | Expr::UnaryOp { expr, op } => { | 340 | Expr::UnaryOp { expr, op } => { |
331 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 341 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
332 | match op { | 342 | match op { |
333 | UnaryOp::Deref => { | 343 | UnaryOp::Deref => match self.resolver.krate() { |
334 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); | 344 | Some(krate) => { |
335 | if let Some(derefed_ty) = | 345 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); |
336 | autoderef::deref(self.db, &self.resolver, &canonicalized.value) | 346 | match autoderef::deref( |
337 | { | 347 | self.db, |
338 | canonicalized.decanonicalize_ty(derefed_ty.value) | 348 | krate, |
339 | } else { | 349 | InEnvironment { |
340 | Ty::Unknown | 350 | value: &canonicalized.value, |
351 | environment: self.trait_env.clone(), | ||
352 | }, | ||
353 | ) { | ||
354 | Some(derefed_ty) => { | ||
355 | canonicalized.decanonicalize_ty(derefed_ty.value) | ||
356 | } | ||
357 | None => Ty::Unknown, | ||
358 | } | ||
341 | } | 359 | } |
342 | } | 360 | None => Ty::Unknown, |
361 | }, | ||
343 | UnaryOp::Neg => { | 362 | UnaryOp::Neg => { |
344 | match &inner_ty { | 363 | match &inner_ty { |
345 | Ty::Apply(a_ty) => match a_ty.ctor { | 364 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -534,7 +553,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
534 | ( | 553 | ( |
535 | ty, | 554 | ty, |
536 | self.db.type_for_def(func.into(), Namespace::Values), | 555 | self.db.type_for_def(func.into(), Namespace::Values), |
537 | Some(func.generic_params(self.db)), | 556 | Some(self.db.generic_params(func.id.into())), |
538 | ) | 557 | ) |
539 | } | 558 | } |
540 | None => (receiver_ty, Ty::Unknown, None), | 559 | None => (receiver_ty, Ty::Unknown, None), |
@@ -645,7 +664,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
645 | if let Some(trait_) = f.parent_trait(self.db) { | 664 | if let Some(trait_) = f.parent_trait(self.db) { |
646 | // construct a TraitDef | 665 | // construct a TraitDef |
647 | let substs = a_ty.parameters.prefix( | 666 | let substs = a_ty.parameters.prefix( |
648 | trait_.generic_params(self.db).count_params_including_parent(), | 667 | self.db |
668 | .generic_params(trait_.id.into()) | ||
669 | .count_params_including_parent(), | ||
649 | ); | 670 | ); |
650 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); | 671 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); |
651 | } | 672 | } |
diff --git a/crates/ra_hir/src/ty/infer/pat.rs b/crates/ra_hir/src/ty/infer/pat.rs index c125ddfbc..641d61e87 100644 --- a/crates/ra_hir/src/ty/infer/pat.rs +++ b/crates/ra_hir/src/ty/infer/pat.rs | |||
@@ -27,10 +27,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
27 | 27 | ||
28 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 28 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
29 | 29 | ||
30 | let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | ||
30 | for (i, &subpat) in subpats.iter().enumerate() { | 31 | for (i, &subpat) in subpats.iter().enumerate() { |
31 | let expected_ty = def | 32 | let expected_ty = def |
32 | .and_then(|d| d.field(self.db, &Name::new_tuple_field(i))) | 33 | .and_then(|d| d.field(self.db, &Name::new_tuple_field(i))) |
33 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 34 | .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) |
34 | .subst(&substs); | 35 | .subst(&substs); |
35 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 36 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
36 | self.infer_pat(subpat, &expected_ty, default_bm); | 37 | self.infer_pat(subpat, &expected_ty, default_bm); |
@@ -56,10 +57,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
56 | 57 | ||
57 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 58 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
58 | 59 | ||
60 | let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | ||
59 | for subpat in subpats { | 61 | for subpat in subpats { |
60 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); | 62 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); |
61 | let expected_ty = | 63 | let expected_ty = matching_field |
62 | matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs); | 64 | .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) |
65 | .subst(&substs); | ||
63 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 66 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
64 | self.infer_pat(subpat.pat, &expected_ty, default_bm); | 67 | self.infer_pat(subpat.pat, &expected_ty, default_bm); |
65 | } | 68 | } |
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index 70136e514..6165eba4f 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs | |||
@@ -7,7 +7,6 @@ use hir_def::{ | |||
7 | 7 | ||
8 | use crate::{ | 8 | use crate::{ |
9 | db::HirDatabase, | 9 | db::HirDatabase, |
10 | generics::HasGenericParams, | ||
11 | ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, | 10 | ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, |
12 | AssocItem, Container, Function, Name, Path, | 11 | AssocItem, Container, Function, Name, Path, |
13 | }; | 12 | }; |
@@ -204,7 +203,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
204 | Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), | 203 | Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), |
205 | Container::Trait(t) => { | 204 | Container::Trait(t) => { |
206 | // we're picking this method | 205 | // we're picking this method |
207 | let trait_substs = Substs::build_for_def(self.db, t) | 206 | let trait_substs = Substs::build_for_def(self.db, t.id) |
208 | .push(ty.clone()) | 207 | .push(ty.clone()) |
209 | .fill(std::iter::repeat_with(|| self.new_type_var())) | 208 | .fill(std::iter::repeat_with(|| self.new_type_var())) |
210 | .build(); | 209 | .build(); |
@@ -230,7 +229,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
230 | if let ValueNs::FunctionId(func) = def { | 229 | if let ValueNs::FunctionId(func) = def { |
231 | let func = Function::from(*func); | 230 | let func = Function::from(*func); |
232 | // We only do the infer if parent has generic params | 231 | // We only do the infer if parent has generic params |
233 | let gen = func.generic_params(self.db); | 232 | let gen = self.db.generic_params(func.id.into()); |
234 | if gen.count_parent_params() == 0 { | 233 | if gen.count_parent_params() == 0 { |
235 | return None; | 234 | return None; |
236 | } | 235 | } |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index c6ad0811b..1ceafd9b1 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -10,27 +10,27 @@ use std::sync::Arc; | |||
10 | 10 | ||
11 | use hir_def::{ | 11 | use hir_def::{ |
12 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType}, | 12 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType}, |
13 | generics::WherePredicate, | ||
13 | path::{GenericArg, PathSegment}, | 14 | path::{GenericArg, PathSegment}, |
14 | resolver::{HasResolver, Resolver, TypeNs}, | 15 | resolver::{HasResolver, Resolver, TypeNs}, |
15 | type_ref::{TypeBound, TypeRef}, | 16 | type_ref::{TypeBound, TypeRef}, |
16 | GenericDefId, | 17 | AdtId, EnumVariantId, GenericDefId, LocalStructFieldId, VariantId, |
17 | }; | 18 | }; |
19 | use ra_arena::map::ArenaMap; | ||
18 | 20 | ||
19 | use super::{ | 21 | use super::{ |
20 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 22 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, |
21 | TypeWalk, | 23 | Ty, TypeCtor, TypeWalk, |
22 | }; | 24 | }; |
23 | use crate::{ | 25 | use crate::{ |
24 | db::HirDatabase, | 26 | db::HirDatabase, |
25 | generics::HasGenericParams, | ||
26 | generics::{GenericDef, WherePredicate}, | ||
27 | ty::{ | 27 | ty::{ |
28 | primitive::{FloatTy, IntTy, Uncertain}, | 28 | primitive::{FloatTy, IntTy, Uncertain}, |
29 | Adt, | 29 | Adt, |
30 | }, | 30 | }, |
31 | util::make_mut_slice, | 31 | util::make_mut_slice, |
32 | Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, StructField, | 32 | Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait, |
33 | Trait, TypeAlias, Union, VariantDef, | 33 | TypeAlias, Union, |
34 | }; | 34 | }; |
35 | 35 | ||
36 | // FIXME: this is only really used in `type_for_def`, which contains a bunch of | 36 | // FIXME: this is only really used in `type_for_def`, which contains a bunch of |
@@ -261,8 +261,10 @@ impl Ty { | |||
261 | let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); | 261 | let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); |
262 | for t in traits { | 262 | for t in traits { |
263 | if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { | 263 | if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { |
264 | let substs = | 264 | let substs = Substs::build_for_def(db, t.id) |
265 | Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build(); | 265 | .push(self_ty.clone()) |
266 | .fill_with_unknown() | ||
267 | .build(); | ||
266 | // FIXME handle type parameters on the segment | 268 | // FIXME handle type parameters on the segment |
267 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); | 269 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); |
268 | } | 270 | } |
@@ -287,11 +289,11 @@ impl Ty { | |||
287 | segment: &PathSegment, | 289 | segment: &PathSegment, |
288 | resolved: TypableDef, | 290 | resolved: TypableDef, |
289 | ) -> Substs { | 291 | ) -> Substs { |
290 | let def_generic: Option<GenericDef> = match resolved { | 292 | let def_generic: Option<GenericDefId> = match resolved { |
291 | TypableDef::Function(func) => Some(func.into()), | 293 | TypableDef::Function(func) => Some(func.id.into()), |
292 | TypableDef::Adt(adt) => Some(adt.into()), | 294 | TypableDef::Adt(adt) => Some(adt.into()), |
293 | TypableDef::EnumVariant(var) => Some(var.parent_enum(db).into()), | 295 | TypableDef::EnumVariant(var) => Some(var.parent_enum(db).id.into()), |
294 | TypableDef::TypeAlias(t) => Some(t.into()), | 296 | TypableDef::TypeAlias(t) => Some(t.id.into()), |
295 | TypableDef::Const(_) | TypableDef::Static(_) | TypableDef::BuiltinType(_) => None, | 297 | TypableDef::Const(_) | TypableDef::Static(_) | TypableDef::BuiltinType(_) => None, |
296 | }; | 298 | }; |
297 | substs_from_path_segment(db, resolver, segment, def_generic, false) | 299 | substs_from_path_segment(db, resolver, segment, def_generic, false) |
@@ -338,11 +340,11 @@ pub(super) fn substs_from_path_segment( | |||
338 | db: &impl HirDatabase, | 340 | db: &impl HirDatabase, |
339 | resolver: &Resolver, | 341 | resolver: &Resolver, |
340 | segment: &PathSegment, | 342 | segment: &PathSegment, |
341 | def_generic: Option<GenericDef>, | 343 | def_generic: Option<GenericDefId>, |
342 | add_self_param: bool, | 344 | add_self_param: bool, |
343 | ) -> Substs { | 345 | ) -> Substs { |
344 | let mut substs = Vec::new(); | 346 | let mut substs = Vec::new(); |
345 | let def_generics = def_generic.map(|def| def.generic_params(db)); | 347 | let def_generics = def_generic.map(|def| db.generic_params(def.into())); |
346 | 348 | ||
347 | let (parent_param_count, param_count) = | 349 | let (parent_param_count, param_count) = |
348 | def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); | 350 | def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); |
@@ -376,7 +378,7 @@ pub(super) fn substs_from_path_segment( | |||
376 | 378 | ||
377 | // handle defaults | 379 | // handle defaults |
378 | if let Some(def_generic) = def_generic { | 380 | if let Some(def_generic) = def_generic { |
379 | let default_substs = db.generic_defaults(def_generic); | 381 | let default_substs = db.generic_defaults(def_generic.into()); |
380 | assert_eq!(substs.len(), default_substs.len()); | 382 | assert_eq!(substs.len(), default_substs.len()); |
381 | 383 | ||
382 | for (i, default_ty) in default_substs.iter().enumerate() { | 384 | for (i, default_ty) in default_substs.iter().enumerate() { |
@@ -439,11 +441,11 @@ impl TraitRef { | |||
439 | ) -> Substs { | 441 | ) -> Substs { |
440 | let has_self_param = | 442 | let has_self_param = |
441 | segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); | 443 | segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); |
442 | substs_from_path_segment(db, resolver, segment, Some(resolved.into()), !has_self_param) | 444 | substs_from_path_segment(db, resolver, segment, Some(resolved.id.into()), !has_self_param) |
443 | } | 445 | } |
444 | 446 | ||
445 | pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { | 447 | pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { |
446 | let substs = Substs::identity(&trait_.generic_params(db)); | 448 | let substs = Substs::identity(&db.generic_params(trait_.id.into())); |
447 | TraitRef { trait_, substs } | 449 | TraitRef { trait_, substs } |
448 | } | 450 | } |
449 | 451 | ||
@@ -550,16 +552,23 @@ pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSi | |||
550 | } | 552 | } |
551 | } | 553 | } |
552 | 554 | ||
553 | /// Build the type of a specific field of a struct or enum variant. | 555 | /// Build the type of all specific fields of a struct or enum variant. |
554 | pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | 556 | pub(crate) fn field_types_query( |
555 | let parent_def = field.parent_def(db); | 557 | db: &impl HirDatabase, |
556 | let resolver = match parent_def { | 558 | variant_id: VariantId, |
557 | VariantDef::Struct(it) => it.id.resolver(db), | 559 | ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { |
558 | VariantDef::EnumVariant(it) => it.parent.id.resolver(db), | 560 | let (resolver, var_data) = match variant_id { |
561 | VariantId::StructId(it) => (it.resolver(db), db.struct_data(it.0).variant_data.clone()), | ||
562 | VariantId::EnumVariantId(it) => ( | ||
563 | it.parent.resolver(db), | ||
564 | db.enum_data(it.parent).variants[it.local_id].variant_data.clone(), | ||
565 | ), | ||
559 | }; | 566 | }; |
560 | let var_data = parent_def.variant_data(db); | 567 | let mut res = ArenaMap::default(); |
561 | let type_ref = &var_data.fields().unwrap()[field.id].type_ref; | 568 | for (field_id, field_data) in var_data.fields().iter() { |
562 | Ty::from_hir(db, &resolver, type_ref) | 569 | res.insert(field_id, Ty::from_hir(db, &resolver, &field_data.type_ref)) |
570 | } | ||
571 | Arc::new(res) | ||
563 | } | 572 | } |
564 | 573 | ||
565 | /// This query exists only to be used when resolving short-hand associated types | 574 | /// This query exists only to be used when resolving short-hand associated types |
@@ -572,10 +581,10 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | |||
572 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. | 581 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. |
573 | pub(crate) fn generic_predicates_for_param_query( | 582 | pub(crate) fn generic_predicates_for_param_query( |
574 | db: &impl HirDatabase, | 583 | db: &impl HirDatabase, |
575 | def: GenericDef, | 584 | def: GenericDefId, |
576 | param_idx: u32, | 585 | param_idx: u32, |
577 | ) -> Arc<[GenericPredicate]> { | 586 | ) -> Arc<[GenericPredicate]> { |
578 | let resolver = GenericDefId::from(def).resolver(db); | 587 | let resolver = def.resolver(db); |
579 | resolver | 588 | resolver |
580 | .where_predicates_in_scope() | 589 | .where_predicates_in_scope() |
581 | // we have to filter out all other predicates *first*, before attempting to lower them | 590 | // we have to filter out all other predicates *first*, before attempting to lower them |
@@ -584,24 +593,23 @@ pub(crate) fn generic_predicates_for_param_query( | |||
584 | .collect() | 593 | .collect() |
585 | } | 594 | } |
586 | 595 | ||
587 | pub(crate) fn trait_env( | 596 | impl TraitEnvironment { |
588 | db: &impl HirDatabase, | 597 | pub(crate) fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { |
589 | resolver: &Resolver, | 598 | let predicates = resolver |
590 | ) -> Arc<super::TraitEnvironment> { | 599 | .where_predicates_in_scope() |
591 | let predicates = resolver | 600 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) |
592 | .where_predicates_in_scope() | 601 | .collect::<Vec<_>>(); |
593 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | ||
594 | .collect::<Vec<_>>(); | ||
595 | 602 | ||
596 | Arc::new(super::TraitEnvironment { predicates }) | 603 | Arc::new(TraitEnvironment { predicates }) |
604 | } | ||
597 | } | 605 | } |
598 | 606 | ||
599 | /// Resolve the where clause(s) of an item with generics. | 607 | /// Resolve the where clause(s) of an item with generics. |
600 | pub(crate) fn generic_predicates_query( | 608 | pub(crate) fn generic_predicates_query( |
601 | db: &impl HirDatabase, | 609 | db: &impl HirDatabase, |
602 | def: GenericDef, | 610 | def: GenericDefId, |
603 | ) -> Arc<[GenericPredicate]> { | 611 | ) -> Arc<[GenericPredicate]> { |
604 | let resolver = GenericDefId::from(def).resolver(db); | 612 | let resolver = def.resolver(db); |
605 | resolver | 613 | resolver |
606 | .where_predicates_in_scope() | 614 | .where_predicates_in_scope() |
607 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 615 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) |
@@ -609,9 +617,9 @@ pub(crate) fn generic_predicates_query( | |||
609 | } | 617 | } |
610 | 618 | ||
611 | /// Resolve the default type params from generics | 619 | /// Resolve the default type params from generics |
612 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) -> Substs { | 620 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { |
613 | let resolver = GenericDefId::from(def).resolver(db); | 621 | let resolver = def.resolver(db); |
614 | let generic_params = def.generic_params(db); | 622 | let generic_params = db.generic_params(def.into()); |
615 | 623 | ||
616 | let defaults = generic_params | 624 | let defaults = generic_params |
617 | .params_including_parent() | 625 | .params_including_parent() |
@@ -623,35 +631,35 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) -> | |||
623 | } | 631 | } |
624 | 632 | ||
625 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { | 633 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { |
626 | let data = def.data(db); | 634 | let data = db.function_data(def.id); |
627 | let resolver = def.id.resolver(db); | 635 | let resolver = def.id.resolver(db); |
628 | let params = data.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); | 636 | let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); |
629 | let ret = Ty::from_hir(db, &resolver, data.ret_type()); | 637 | let ret = Ty::from_hir(db, &resolver, &data.ret_type); |
630 | FnSig::from_params_and_return(params, ret) | 638 | FnSig::from_params_and_return(params, ret) |
631 | } | 639 | } |
632 | 640 | ||
633 | /// Build the declared type of a function. This should not need to look at the | 641 | /// Build the declared type of a function. This should not need to look at the |
634 | /// function body. | 642 | /// function body. |
635 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 643 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { |
636 | let generics = def.generic_params(db); | 644 | let generics = db.generic_params(def.id.into()); |
637 | let substs = Substs::identity(&generics); | 645 | let substs = Substs::identity(&generics); |
638 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 646 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
639 | } | 647 | } |
640 | 648 | ||
641 | /// Build the declared type of a const. | 649 | /// Build the declared type of a const. |
642 | fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { | 650 | fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { |
643 | let data = def.data(db); | 651 | let data = db.const_data(def.id); |
644 | let resolver = def.id.resolver(db); | 652 | let resolver = def.id.resolver(db); |
645 | 653 | ||
646 | Ty::from_hir(db, &resolver, data.type_ref()) | 654 | Ty::from_hir(db, &resolver, &data.type_ref) |
647 | } | 655 | } |
648 | 656 | ||
649 | /// Build the declared type of a static. | 657 | /// Build the declared type of a static. |
650 | fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { | 658 | fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { |
651 | let data = def.data(db); | 659 | let data = db.static_data(def.id); |
652 | let resolver = def.id.resolver(db); | 660 | let resolver = def.id.resolver(db); |
653 | 661 | ||
654 | Ty::from_hir(db, &resolver, data.type_ref()) | 662 | Ty::from_hir(db, &resolver, &data.type_ref) |
655 | } | 663 | } |
656 | 664 | ||
657 | /// Build the declared type of a static. | 665 | /// Build the declared type of a static. |
@@ -697,10 +705,7 @@ impl From<Option<BuiltinFloat>> for Uncertain<FloatTy> { | |||
697 | 705 | ||
698 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { | 706 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { |
699 | let struct_data = db.struct_data(def.id.into()); | 707 | let struct_data = db.struct_data(def.id.into()); |
700 | let fields = match struct_data.variant_data.fields() { | 708 | let fields = struct_data.variant_data.fields(); |
701 | Some(fields) => fields, | ||
702 | None => panic!("fn_sig_for_struct_constructor called on unit struct"), | ||
703 | }; | ||
704 | let resolver = def.id.resolver(db); | 709 | let resolver = def.id.resolver(db); |
705 | let params = fields | 710 | let params = fields |
706 | .iter() | 711 | .iter() |
@@ -713,26 +718,23 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { | |||
713 | /// Build the type of a tuple struct constructor. | 718 | /// Build the type of a tuple struct constructor. |
714 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | 719 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { |
715 | let struct_data = db.struct_data(def.id.into()); | 720 | let struct_data = db.struct_data(def.id.into()); |
716 | if struct_data.variant_data.fields().is_none() { | 721 | if struct_data.variant_data.is_unit() { |
717 | return type_for_adt(db, def); // Unit struct | 722 | return type_for_adt(db, def); // Unit struct |
718 | } | 723 | } |
719 | let generics = def.generic_params(db); | 724 | let generics = db.generic_params(def.id.into()); |
720 | let substs = Substs::identity(&generics); | 725 | let substs = Substs::identity(&generics); |
721 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 726 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
722 | } | 727 | } |
723 | 728 | ||
724 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { | 729 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { |
725 | let var_data = def.variant_data(db); | 730 | let var_data = def.variant_data(db); |
726 | let fields = match var_data.fields() { | 731 | let fields = var_data.fields(); |
727 | Some(fields) => fields, | ||
728 | None => panic!("fn_sig_for_enum_variant_constructor called for unit variant"), | ||
729 | }; | ||
730 | let resolver = def.parent.id.resolver(db); | 732 | let resolver = def.parent.id.resolver(db); |
731 | let params = fields | 733 | let params = fields |
732 | .iter() | 734 | .iter() |
733 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 735 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
734 | .collect::<Vec<_>>(); | 736 | .collect::<Vec<_>>(); |
735 | let generics = def.parent_enum(db).generic_params(db); | 737 | let generics = db.generic_params(def.parent_enum(db).id.into()); |
736 | let substs = Substs::identity(&generics); | 738 | let substs = Substs::identity(&generics); |
737 | let ret = type_for_adt(db, def.parent_enum(db)).subst(&substs); | 739 | let ret = type_for_adt(db, def.parent_enum(db)).subst(&substs); |
738 | FnSig::from_params_and_return(params, ret) | 740 | FnSig::from_params_and_return(params, ret) |
@@ -741,21 +743,23 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) | |||
741 | /// Build the type of a tuple enum variant constructor. | 743 | /// Build the type of a tuple enum variant constructor. |
742 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { | 744 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { |
743 | let var_data = def.variant_data(db); | 745 | let var_data = def.variant_data(db); |
744 | if var_data.fields().is_none() { | 746 | if var_data.is_unit() { |
745 | return type_for_adt(db, def.parent_enum(db)); // Unit variant | 747 | return type_for_adt(db, def.parent_enum(db)); // Unit variant |
746 | } | 748 | } |
747 | let generics = def.parent_enum(db).generic_params(db); | 749 | let generics = db.generic_params(def.parent_enum(db).id.into()); |
748 | let substs = Substs::identity(&generics); | 750 | let substs = Substs::identity(&generics); |
749 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 751 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
750 | } | 752 | } |
751 | 753 | ||
752 | fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt> + HasGenericParams) -> Ty { | 754 | fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt>) -> Ty { |
753 | let generics = adt.generic_params(db); | 755 | let adt = adt.into(); |
754 | Ty::apply(TypeCtor::Adt(adt.into()), Substs::identity(&generics)) | 756 | let adt_id: AdtId = adt.into(); |
757 | let generics = db.generic_params(adt_id.into()); | ||
758 | Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) | ||
755 | } | 759 | } |
756 | 760 | ||
757 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { | 761 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { |
758 | let generics = t.generic_params(db); | 762 | let generics = db.generic_params(t.id.into()); |
759 | let resolver = t.id.resolver(db); | 763 | let resolver = t.id.resolver(db); |
760 | let type_ref = t.type_ref(db); | 764 | let type_ref = t.type_ref(db); |
761 | let substs = Substs::identity(&generics); | 765 | let substs = Substs::identity(&generics); |
@@ -817,12 +821,12 @@ impl CallableDef { | |||
817 | } | 821 | } |
818 | } | 822 | } |
819 | 823 | ||
820 | impl From<CallableDef> for GenericDef { | 824 | impl From<CallableDef> for GenericDefId { |
821 | fn from(def: CallableDef) -> GenericDef { | 825 | fn from(def: CallableDef) -> GenericDefId { |
822 | match def { | 826 | match def { |
823 | CallableDef::Function(f) => f.into(), | 827 | CallableDef::Function(f) => f.id.into(), |
824 | CallableDef::Struct(s) => s.into(), | 828 | CallableDef::Struct(s) => s.id.into(), |
825 | CallableDef::EnumVariant(e) => e.into(), | 829 | CallableDef::EnumVariant(e) => EnumVariantId::from(e).into(), |
826 | } | 830 | } |
827 | } | 831 | } |
828 | } | 832 | } |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 64adb814d..c5ab690eb 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::resolver::Resolver; | 8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef}; |
9 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, | 15 | AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 18 | use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; |
19 | 19 | ||
20 | /// This is used as a key for indexing impls. | 20 | /// This is used as a key for indexing impls. |
21 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 21 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
@@ -91,34 +91,43 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayV | |||
91 | // Types like slice can have inherent impls in several crates, (core and alloc). | 91 | // Types like slice can have inherent impls in several crates, (core and alloc). |
92 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. | 92 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. |
93 | macro_rules! lang_item_crate { | 93 | macro_rules! lang_item_crate { |
94 | ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ | 94 | ($($name:expr),+ $(,)?) => {{ |
95 | let mut v = ArrayVec::<[Crate; 2]>::new(); | 95 | let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); |
96 | $( | 96 | $( |
97 | v.extend($db.lang_item($cur_crate, $name.into()).and_then(|item| item.krate($db))); | 97 | v.extend(db.lang_item(cur_crate.crate_id, $name.into())); |
98 | )+ | 98 | )+ |
99 | Some(v) | 99 | v |
100 | }}; | 100 | }}; |
101 | } | 101 | } |
102 | 102 | ||
103 | match ty { | 103 | let lang_item_targets = match ty { |
104 | Ty::Apply(a_ty) => match a_ty.ctor { | 104 | Ty::Apply(a_ty) => match a_ty.ctor { |
105 | TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()), | 105 | TypeCtor::Adt(def_id) => return Some(std::iter::once(def_id.krate(db)?).collect()), |
106 | TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"), | 106 | TypeCtor::Bool => lang_item_crate!("bool"), |
107 | TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"), | 107 | TypeCtor::Char => lang_item_crate!("char"), |
108 | TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { | 108 | TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { |
109 | // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) | 109 | // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) |
110 | FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"), | 110 | FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), |
111 | FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"), | 111 | FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"), |
112 | }, | 112 | }, |
113 | TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(db, cur_crate, i.ty_to_string()), | 113 | TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()), |
114 | TypeCtor::Str => lang_item_crate!(db, cur_crate, "str_alloc", "str"), | 114 | TypeCtor::Str => lang_item_crate!("str_alloc", "str"), |
115 | TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), | 115 | TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"), |
116 | TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!(db, cur_crate, "const_ptr"), | 116 | TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"), |
117 | TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!(db, cur_crate, "mut_ptr"), | 117 | TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), |
118 | _ => None, | 118 | _ => return None, |
119 | }, | 119 | }, |
120 | _ => None, | 120 | _ => return None, |
121 | } | 121 | }; |
122 | let res = lang_item_targets | ||
123 | .into_iter() | ||
124 | .filter_map(|it| match it { | ||
125 | LangItemTarget::ImplBlockId(it) => Some(it), | ||
126 | _ => None, | ||
127 | }) | ||
128 | .map(|it| it.module(db).krate.into()) | ||
129 | .collect(); | ||
130 | Some(res) | ||
122 | } | 131 | } |
123 | 132 | ||
124 | /// Look up the method with the given name, returning the actual autoderefed | 133 | /// Look up the method with the given name, returning the actual autoderefed |
@@ -170,8 +179,9 @@ pub(crate) fn iterate_method_candidates<T>( | |||
170 | // Also note that when we've got a receiver like &S, even if the method we | 179 | // Also note that when we've got a receiver like &S, even if the method we |
171 | // find in the end takes &self, we still do the autoderef step (just as | 180 | // find in the end takes &self, we still do the autoderef step (just as |
172 | // rustc does an autoderef and then autoref again). | 181 | // rustc does an autoderef and then autoref again). |
173 | 182 | let environment = TraitEnvironment::lower(db, resolver); | |
174 | for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { | 183 | let ty = InEnvironment { value: ty.clone(), environment }; |
184 | for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) { | ||
175 | if let Some(result) = iterate_inherent_methods( | 185 | if let Some(result) = iterate_inherent_methods( |
176 | &derefed_ty, | 186 | &derefed_ty, |
177 | db, | 187 | db, |
@@ -221,7 +231,7 @@ fn iterate_trait_method_candidates<T>( | |||
221 | ) -> Option<T> { | 231 | ) -> Option<T> { |
222 | let krate = resolver.krate()?; | 232 | let krate = resolver.krate()?; |
223 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) | 233 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) |
224 | let env = lower::trait_env(db, resolver); | 234 | let env = TraitEnvironment::lower(db, resolver); |
225 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope | 235 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope |
226 | let inherent_trait = ty.value.inherent_trait().into_iter(); | 236 | let inherent_trait = ty.value.inherent_trait().into_iter(); |
227 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 237 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope |
@@ -233,7 +243,7 @@ fn iterate_trait_method_candidates<T>( | |||
233 | .chain(traits_from_env) | 243 | .chain(traits_from_env) |
234 | .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from)); | 244 | .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from)); |
235 | 'traits: for t in traits { | 245 | 'traits: for t in traits { |
236 | let data = t.trait_data(db); | 246 | let data = db.trait_data(t.id); |
237 | 247 | ||
238 | // we'll be lazy about checking whether the type implements the | 248 | // we'll be lazy about checking whether the type implements the |
239 | // trait, but if we find out it doesn't, we'll skip the rest of the | 249 | // trait, but if we find out it doesn't, we'll skip the rest of the |
@@ -291,9 +301,9 @@ fn is_valid_candidate( | |||
291 | ) -> bool { | 301 | ) -> bool { |
292 | match item { | 302 | match item { |
293 | AssocItem::Function(m) => { | 303 | AssocItem::Function(m) => { |
294 | let data = m.data(db); | 304 | let data = db.function_data(m.id); |
295 | name.map_or(true, |name| data.name() == name) | 305 | name.map_or(true, |name| data.name == *name) |
296 | && (data.has_self_param() || mode == LookupMode::Path) | 306 | && (data.has_self_param || mode == LookupMode::Path) |
297 | } | 307 | } |
298 | AssocItem::Const(c) => { | 308 | AssocItem::Const(c) => { |
299 | name.map_or(true, |name| Some(name) == c.name(db).as_ref()) | 309 | name.map_or(true, |name| Some(name) == c.name(db).as_ref()) |
@@ -315,7 +325,7 @@ pub(crate) fn implements_trait( | |||
315 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | 325 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet |
316 | return true; | 326 | return true; |
317 | } | 327 | } |
318 | let env = lower::trait_env(db, resolver); | 328 | let env = TraitEnvironment::lower(db, resolver); |
319 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 329 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
320 | let solution = db.trait_solve(krate, goal); | 330 | let solution = db.trait_solve(krate, goal); |
321 | 331 | ||
@@ -355,7 +365,7 @@ fn generic_implements_goal( | |||
355 | self_ty: Canonical<Ty>, | 365 | self_ty: Canonical<Ty>, |
356 | ) -> Canonical<InEnvironment<super::Obligation>> { | 366 | ) -> Canonical<InEnvironment<super::Obligation>> { |
357 | let num_vars = self_ty.num_vars; | 367 | let num_vars = self_ty.num_vars; |
358 | let substs = super::Substs::build_for_def(db, trait_) | 368 | let substs = super::Substs::build_for_def(db, trait_.id) |
359 | .push(self_ty.value) | 369 | .push(self_ty.value) |
360 | .fill_with_bound_vars(num_vars as u32) | 370 | .fill_with_bound_vars(num_vars as u32) |
361 | .build(); | 371 | .build(); |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 74c12a0a2..3209c66bd 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2550,8 +2550,6 @@ fn test() { | |||
2550 | [233; 246) 'GLOBAL_STATIC': u32 | 2550 | [233; 246) 'GLOBAL_STATIC': u32 |
2551 | [256; 257) 'w': u32 | 2551 | [256; 257) 'w': u32 |
2552 | [260; 277) 'GLOBAL...IC_MUT': u32 | 2552 | [260; 277) 'GLOBAL...IC_MUT': u32 |
2553 | [118; 120) '99': u32 | ||
2554 | [161; 163) '99': u32 | ||
2555 | "### | 2553 | "### |
2556 | ); | 2554 | ); |
2557 | } | 2555 | } |
@@ -4857,3 +4855,41 @@ fn main() { | |||
4857 | "### | 4855 | "### |
4858 | ); | 4856 | ); |
4859 | } | 4857 | } |
4858 | |||
4859 | #[test] | ||
4860 | fn infer_builtin_macros_file() { | ||
4861 | assert_snapshot!( | ||
4862 | infer(r#" | ||
4863 | #[rustc_builtin_macro] | ||
4864 | macro_rules! file {() => {}} | ||
4865 | |||
4866 | fn main() { | ||
4867 | let x = file!(); | ||
4868 | } | ||
4869 | "#), | ||
4870 | @r###" | ||
4871 | ![0; 2) '""': &str | ||
4872 | [64; 88) '{ ...!(); }': () | ||
4873 | [74; 75) 'x': &str | ||
4874 | "### | ||
4875 | ); | ||
4876 | } | ||
4877 | |||
4878 | #[test] | ||
4879 | fn infer_builtin_macros_column() { | ||
4880 | assert_snapshot!( | ||
4881 | infer(r#" | ||
4882 | #[rustc_builtin_macro] | ||
4883 | macro_rules! column {() => {}} | ||
4884 | |||
4885 | fn main() { | ||
4886 | let x = column!(); | ||
4887 | } | ||
4888 | "#), | ||
4889 | @r###" | ||
4890 | ![0; 2) '13': i32 | ||
4891 | [66; 92) '{ ...!(); }': () | ||
4892 | [76; 77) 'x': i32 | ||
4893 | "### | ||
4894 | ); | ||
4895 | } | ||
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index 45f725438..268fa09e4 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex}; | |||
3 | 3 | ||
4 | use chalk_ir::{cast::Cast, family::ChalkIr}; | 4 | use chalk_ir::{cast::Cast, family::ChalkIr}; |
5 | use log::debug; | 5 | use log::debug; |
6 | use ra_db::salsa; | 6 | use ra_db::{impl_intern_key, salsa}; |
7 | use ra_prof::profile; | 7 | use ra_prof::profile; |
8 | use rustc_hash::FxHashSet; | 8 | use rustc_hash::FxHashSet; |
9 | 9 | ||
@@ -304,6 +304,10 @@ pub enum Impl { | |||
304 | /// Closure types implement the Fn traits synthetically. | 304 | /// Closure types implement the Fn traits synthetically. |
305 | ClosureFnTraitImpl(ClosureFnTraitImplData), | 305 | ClosureFnTraitImpl(ClosureFnTraitImplData), |
306 | } | 306 | } |
307 | /// This exists just for Chalk, because our ImplIds are only unique per module. | ||
308 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
309 | pub struct GlobalImplId(salsa::InternId); | ||
310 | impl_intern_key!(GlobalImplId); | ||
307 | 311 | ||
308 | /// An associated type value. Usually this comes from a `type` declaration | 312 | /// An associated type value. Usually this comes from a `type` declaration |
309 | /// inside an impl block, but for built-in impls we have to synthesize it. | 313 | /// inside an impl block, but for built-in impls we have to synthesize it. |
@@ -315,3 +319,8 @@ pub enum AssocTyValue { | |||
315 | /// The output type of the Fn trait implementation. | 319 | /// The output type of the Fn trait implementation. |
316 | ClosureFnTraitImplOutput(ClosureFnTraitImplData), | 320 | ClosureFnTraitImplOutput(ClosureFnTraitImplData), |
317 | } | 321 | } |
322 | /// This exists just for Chalk, because it needs a unique ID for each associated | ||
323 | /// type value in an impl (even synthetic ones). | ||
324 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
325 | pub struct AssocTyValueId(salsa::InternId); | ||
326 | impl_intern_key!(AssocTyValueId); | ||
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 9bf93981a..0272dd9ae 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -9,6 +9,7 @@ use chalk_ir::{ | |||
9 | }; | 9 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use hir_def::{lang_item::LangItemTarget, GenericDefId}; | ||
12 | use hir_expand::name; | 13 | use hir_expand::name; |
13 | 14 | ||
14 | use ra_db::salsa::{InternId, InternKey}; | 15 | use ra_db::salsa::{InternId, InternKey}; |
@@ -16,10 +17,9 @@ use ra_db::salsa::{InternId, InternKey}; | |||
16 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 17 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
17 | use crate::{ | 18 | use crate::{ |
18 | db::HirDatabase, | 19 | db::HirDatabase, |
19 | generics::{GenericDef, HasGenericParams}, | ||
20 | ty::display::HirDisplay, | 20 | ty::display::HirDisplay, |
21 | ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, | 21 | ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, |
22 | Crate, HasBody, ImplBlock, Trait, TypeAlias, | 22 | Crate, ImplBlock, Trait, TypeAlias, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | /// This represents a trait whose name we could not resolve. | 25 | /// This represents a trait whose name we could not resolve. |
@@ -402,7 +402,7 @@ fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | |||
402 | 402 | ||
403 | fn convert_where_clauses( | 403 | fn convert_where_clauses( |
404 | db: &impl HirDatabase, | 404 | db: &impl HirDatabase, |
405 | def: GenericDef, | 405 | def: GenericDefId, |
406 | substs: &Substs, | 406 | substs: &Substs, |
407 | ) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> { | 407 | ) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> { |
408 | let generic_predicates = db.generic_predicates(def); | 408 | let generic_predicates = db.generic_predicates(def); |
@@ -509,7 +509,7 @@ pub(crate) fn associated_ty_data_query( | |||
509 | Some(crate::Container::Trait(t)) => t, | 509 | Some(crate::Container::Trait(t)) => t, |
510 | _ => panic!("associated type not in trait"), | 510 | _ => panic!("associated type not in trait"), |
511 | }; | 511 | }; |
512 | let generic_params = type_alias.generic_params(db); | 512 | let generic_params = db.generic_params(type_alias.id.into()); |
513 | let bound_data = chalk_rust_ir::AssociatedTyDatumBound { | 513 | let bound_data = chalk_rust_ir::AssociatedTyDatumBound { |
514 | // FIXME add bounds and where clauses | 514 | // FIXME add bounds and where clauses |
515 | bounds: vec![], | 515 | bounds: vec![], |
@@ -550,7 +550,7 @@ pub(crate) fn trait_datum_query( | |||
550 | } | 550 | } |
551 | let trait_: Trait = from_chalk(db, trait_id); | 551 | let trait_: Trait = from_chalk(db, trait_id); |
552 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); | 552 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); |
553 | let generic_params = trait_.generic_params(db); | 553 | let generic_params = db.generic_params(trait_.id.into()); |
554 | let bound_vars = Substs::bound_vars(&generic_params); | 554 | let bound_vars = Substs::bound_vars(&generic_params); |
555 | let flags = chalk_rust_ir::TraitFlags { | 555 | let flags = chalk_rust_ir::TraitFlags { |
556 | auto: trait_.is_auto(db), | 556 | auto: trait_.is_auto(db), |
@@ -561,7 +561,7 @@ pub(crate) fn trait_datum_query( | |||
561 | marker: false, | 561 | marker: false, |
562 | fundamental: false, | 562 | fundamental: false, |
563 | }; | 563 | }; |
564 | let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); | 564 | let where_clauses = convert_where_clauses(db, trait_.id.into(), &bound_vars); |
565 | let associated_ty_ids = trait_ | 565 | let associated_ty_ids = trait_ |
566 | .items(db) | 566 | .items(db) |
567 | .into_iter() | 567 | .into_iter() |
@@ -594,7 +594,7 @@ pub(crate) fn struct_datum_query( | |||
594 | let where_clauses = type_ctor | 594 | let where_clauses = type_ctor |
595 | .as_generic_def() | 595 | .as_generic_def() |
596 | .map(|generic_def| { | 596 | .map(|generic_def| { |
597 | let generic_params = generic_def.generic_params(db); | 597 | let generic_params = db.generic_params(generic_def.into()); |
598 | let bound_vars = Substs::bound_vars(&generic_params); | 598 | let bound_vars = Substs::bound_vars(&generic_params); |
599 | convert_where_clauses(db, generic_def, &bound_vars) | 599 | convert_where_clauses(db, generic_def, &bound_vars) |
600 | }) | 600 | }) |
@@ -634,7 +634,7 @@ fn impl_block_datum( | |||
634 | impl_id: ImplId, | 634 | impl_id: ImplId, |
635 | impl_block: ImplBlock, | 635 | impl_block: ImplBlock, |
636 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { | 636 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { |
637 | let generic_params = impl_block.generic_params(db); | 637 | let generic_params = db.generic_params(impl_block.id.into()); |
638 | let bound_vars = Substs::bound_vars(&generic_params); | 638 | let bound_vars = Substs::bound_vars(&generic_params); |
639 | let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); | 639 | let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); |
640 | let trait_ = trait_ref.trait_; | 640 | let trait_ = trait_ref.trait_; |
@@ -643,7 +643,7 @@ fn impl_block_datum( | |||
643 | } else { | 643 | } else { |
644 | chalk_rust_ir::ImplType::External | 644 | chalk_rust_ir::ImplType::External |
645 | }; | 645 | }; |
646 | let where_clauses = convert_where_clauses(db, impl_block.into(), &bound_vars); | 646 | let where_clauses = convert_where_clauses(db, impl_block.id.into(), &bound_vars); |
647 | let negative = impl_block.is_negative(db); | 647 | let negative = impl_block.is_negative(db); |
648 | debug!( | 648 | debug!( |
649 | "impl {:?}: {}{} where {:?}", | 649 | "impl {:?}: {}{} where {:?}", |
@@ -715,7 +715,7 @@ fn closure_fn_trait_impl_datum( | |||
715 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | 715 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; |
716 | fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | 716 | fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; |
717 | 717 | ||
718 | let num_args: u16 = match &data.def.body(db)[data.expr] { | 718 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { |
719 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | 719 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, |
720 | _ => { | 720 | _ => { |
721 | log::warn!("closure for closure type {:?} not found", data); | 721 | log::warn!("closure for closure type {:?} not found", data); |
@@ -736,7 +736,7 @@ fn closure_fn_trait_impl_datum( | |||
736 | 736 | ||
737 | let trait_ref = TraitRef { | 737 | let trait_ref = TraitRef { |
738 | trait_, | 738 | trait_, |
739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | 739 | substs: Substs::build_for_def(db, trait_.id).push(self_ty).push(arg_ty).build(), |
740 | }; | 740 | }; |
741 | 741 | ||
742 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); | 742 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); |
@@ -786,7 +786,7 @@ fn type_alias_associated_ty_value( | |||
786 | let assoc_ty = trait_ | 786 | let assoc_ty = trait_ |
787 | .associated_type_by_name(db, &type_alias.name(db)) | 787 | .associated_type_by_name(db, &type_alias.name(db)) |
788 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | 788 | .expect("assoc ty value should not exist"); // validated when building the impl data as well |
789 | let generic_params = impl_block.generic_params(db); | 789 | let generic_params = db.generic_params(impl_block.id.into()); |
790 | let bound_vars = Substs::bound_vars(&generic_params); | 790 | let bound_vars = Substs::bound_vars(&generic_params); |
791 | let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); | 791 | let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); |
792 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; | 792 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; |
@@ -805,7 +805,7 @@ fn closure_fn_trait_output_assoc_ty_value( | |||
805 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | 805 | ) -> Arc<AssociatedTyValue<ChalkIr>> { |
806 | let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); | 806 | let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); |
807 | 807 | ||
808 | let num_args: u16 = match &data.def.body(db)[data.expr] { | 808 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { |
809 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | 809 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, |
810 | _ => { | 810 | _ => { |
811 | log::warn!("closure for closure type {:?} not found", data); | 811 | log::warn!("closure for closure type {:?} not found", data); |
@@ -833,9 +833,9 @@ fn closure_fn_trait_output_assoc_ty_value( | |||
833 | } | 833 | } |
834 | 834 | ||
835 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | 835 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { |
836 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; | 836 | let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?; |
837 | match target { | 837 | match target { |
838 | crate::lang_item::LangItemTarget::Trait(t) => Some(t), | 838 | LangItemTarget::TraitId(t) => Some(t.into()), |
839 | _ => None, | 839 | _ => None, |
840 | } | 840 | } |
841 | } | 841 | } |
@@ -847,38 +847,38 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId { | |||
847 | chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } | 847 | chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } |
848 | } | 848 | } |
849 | 849 | ||
850 | impl From<chalk_ir::StructId> for crate::ids::TypeCtorId { | 850 | impl From<chalk_ir::StructId> for crate::ty::TypeCtorId { |
851 | fn from(struct_id: chalk_ir::StructId) -> Self { | 851 | fn from(struct_id: chalk_ir::StructId) -> Self { |
852 | id_from_chalk(struct_id.0) | 852 | id_from_chalk(struct_id.0) |
853 | } | 853 | } |
854 | } | 854 | } |
855 | 855 | ||
856 | impl From<crate::ids::TypeCtorId> for chalk_ir::StructId { | 856 | impl From<crate::ty::TypeCtorId> for chalk_ir::StructId { |
857 | fn from(type_ctor_id: crate::ids::TypeCtorId) -> Self { | 857 | fn from(type_ctor_id: crate::ty::TypeCtorId) -> Self { |
858 | chalk_ir::StructId(id_to_chalk(type_ctor_id)) | 858 | chalk_ir::StructId(id_to_chalk(type_ctor_id)) |
859 | } | 859 | } |
860 | } | 860 | } |
861 | 861 | ||
862 | impl From<chalk_ir::ImplId> for crate::ids::GlobalImplId { | 862 | impl From<chalk_ir::ImplId> for crate::ty::traits::GlobalImplId { |
863 | fn from(impl_id: chalk_ir::ImplId) -> Self { | 863 | fn from(impl_id: chalk_ir::ImplId) -> Self { |
864 | id_from_chalk(impl_id.0) | 864 | id_from_chalk(impl_id.0) |
865 | } | 865 | } |
866 | } | 866 | } |
867 | 867 | ||
868 | impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId { | 868 | impl From<crate::ty::traits::GlobalImplId> for chalk_ir::ImplId { |
869 | fn from(impl_id: crate::ids::GlobalImplId) -> Self { | 869 | fn from(impl_id: crate::ty::traits::GlobalImplId) -> Self { |
870 | chalk_ir::ImplId(id_to_chalk(impl_id)) | 870 | chalk_ir::ImplId(id_to_chalk(impl_id)) |
871 | } | 871 | } |
872 | } | 872 | } |
873 | 873 | ||
874 | impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId { | 874 | impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ty::traits::AssocTyValueId { |
875 | fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { | 875 | fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { |
876 | id_from_chalk(id.0) | 876 | id_from_chalk(id.0) |
877 | } | 877 | } |
878 | } | 878 | } |
879 | 879 | ||
880 | impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { | 880 | impl From<crate::ty::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { |
881 | fn from(assoc_ty_value_id: crate::ids::AssocTyValueId) -> Self { | 881 | fn from(assoc_ty_value_id: crate::ty::traits::AssocTyValueId) -> Self { |
882 | chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) | 882 | chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) |
883 | } | 883 | } |
884 | } | 884 | } |