aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-11-25 00:54:54 +0000
committerSeivan Heidari <[email protected]>2019-11-25 00:54:54 +0000
commit15ea338ac991707d330288ba4d1bf5daa0fc75d9 (patch)
tree16aeab28bcdb07d36aae28e3fb4a385614865a48 /crates/ra_hir/src/ty
parenteb7363d167c7a9f7c73cb950b621eb1dce493318 (diff)
parentf7f9757b6b144385ab8ce57b15764473b1f57331 (diff)
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs7
-rw-r--r--crates/ra_hir/src/ty/infer.rs29
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs20
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs33
-rw-r--r--crates/ra_hir/src/ty/infer/pat.rs9
-rw-r--r--crates/ra_hir/src/ty/lower.rs58
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs55
-rw-r--r--crates/ra_hir/src/ty/tests.rs40
-rw-r--r--crates/ra_hir/src/ty/traits.rs11
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs29
10 files changed, 184 insertions, 107 deletions
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index b60e4bb31..41c99d227 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -5,12 +5,13 @@
5 5
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_def::resolver::Resolver; 8use hir_def::{lang_item::LangItemTarget, resolver::Resolver};
9use hir_expand::name; 9use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11 11
12use crate::{db::HirDatabase, Trait};
13
12use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; 14use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
13use crate::db::HirDatabase;
14 15
15const AUTODEREF_RECURSION_LIMIT: usize = 10; 16const AUTODEREF_RECURSION_LIMIT: usize = 10;
16 17
@@ -41,7 +42,7 @@ fn deref_by_trait(
41) -> Option<Canonical<Ty>> { 42) -> Option<Canonical<Ty>> {
42 let krate = resolver.krate()?; 43 let krate = resolver.krate()?;
43 let deref_trait = match db.lang_item(krate.into(), "deref".into())? { 44 let deref_trait = match db.lang_item(krate.into(), "deref".into())? {
44 crate::lang_item::LangItemTarget::Trait(t) => t, 45 LangItemTarget::TraitId(t) => Trait::from(t),
45 _ => return None, 46 _ => return None,
46 }; 47 };
47 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; 48 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?;
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 69b13baef..ddc7d262a 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};
22use rustc_hash::FxHashMap; 22use rustc_hash::FxHashMap;
23 23
24use hir_def::{ 24use 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},
@@ -43,8 +44,7 @@ use crate::{
43 db::HirDatabase, 44 db::HirDatabase,
44 expr::{BindingAnnotation, Body, ExprId, PatId}, 45 expr::{BindingAnnotation, Body, ExprId, PatId},
45 ty::infer::diagnostics::InferenceDiagnostic, 46 ty::infer::diagnostics::InferenceDiagnostic,
46 Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, 47 Adt, AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, Trait, VariantDef,
47 StructField, Trait, VariantDef,
48}; 48};
49 49
50macro_rules! ty_app { 50macro_rules! ty_app {
@@ -68,10 +68,10 @@ pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResu
68 let resolver = DefWithBodyId::from(def).resolver(db); 68 let resolver = DefWithBodyId::from(def).resolver(db);
69 let mut ctx = InferenceContext::new(db, def, resolver); 69 let mut ctx = InferenceContext::new(db, def, resolver);
70 70
71 match def { 71 match &def {
72 DefWithBody::Const(ref c) => ctx.collect_const(&c.data(db)), 72 DefWithBody::Const(c) => ctx.collect_const(&db.const_data(c.id)),
73 DefWithBody::Function(ref f) => ctx.collect_fn(&f.data(db)), 73 DefWithBody::Function(f) => ctx.collect_fn(&db.function_data(f.id)),
74 DefWithBody::Static(ref s) => ctx.collect_const(&s.data(db)), 74 DefWithBody::Static(s) => ctx.collect_const(&db.static_data(s.id)),
75 } 75 }
76 76
77 ctx.infer_body(); 77 ctx.infer_body();
@@ -125,6 +125,8 @@ pub struct InferenceResult {
125 method_resolutions: FxHashMap<ExprId, Function>, 125 method_resolutions: FxHashMap<ExprId, Function>,
126 /// For each field access expr, records the field it resolves to. 126 /// For each field access expr, records the field it resolves to.
127 field_resolutions: FxHashMap<ExprId, StructField>, 127 field_resolutions: FxHashMap<ExprId, StructField>,
128 /// For each field in record literal, records the field it resolves to.
129 record_field_resolutions: FxHashMap<ExprId, StructField>,
128 /// For each struct literal, records the variant it resolves to. 130 /// For each struct literal, records the variant it resolves to.
129 variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, 131 variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>,
130 /// For each associated item record what it resolves to 132 /// For each associated item record what it resolves to
@@ -142,6 +144,9 @@ impl InferenceResult {
142 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { 144 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> {
143 self.field_resolutions.get(&expr).copied() 145 self.field_resolutions.get(&expr).copied()
144 } 146 }
147 pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructField> {
148 self.record_field_resolutions.get(&expr).copied()
149 }
145 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantDef> { 150 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantDef> {
146 self.variant_resolutions.get(&id.into()).copied() 151 self.variant_resolutions.get(&id.into()).copied()
147 } 152 }
@@ -215,7 +220,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
215 coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), 220 coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver),
216 db, 221 db,
217 owner, 222 owner,
218 body: owner.body(db), 223 body: db.body(owner.into()),
219 resolver, 224 resolver,
220 } 225 }
221 } 226 }
@@ -559,21 +564,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
559 } 564 }
560 565
561 fn collect_const(&mut self, data: &ConstData) { 566 fn collect_const(&mut self, data: &ConstData) {
562 self.return_ty = self.make_ty(data.type_ref()); 567 self.return_ty = self.make_ty(&data.type_ref);
563 } 568 }
564 569
565 fn collect_fn(&mut self, data: &FnData) { 570 fn collect_fn(&mut self, data: &FunctionData) {
566 let body = Arc::clone(&self.body); // avoid borrow checker problem 571 let body = Arc::clone(&self.body); // avoid borrow checker problem
567 for (type_ref, pat) in data.params().iter().zip(body.params()) { 572 for (type_ref, pat) in data.params.iter().zip(body.params.iter()) {
568 let ty = self.make_ty(type_ref); 573 let ty = self.make_ty(type_ref);
569 574
570 self.infer_pat(*pat, &ty, BindingMode::default()); 575 self.infer_pat(*pat, &ty, BindingMode::default());
571 } 576 }
572 self.return_ty = self.make_ty(data.ret_type()); 577 self.return_ty = self.make_ty(&data.ret_type);
573 } 578 }
574 579
575 fn infer_body(&mut self) { 580 fn infer_body(&mut self) {
576 self.infer_expr(self.body.body_expr(), &Expectation::has_type(self.return_ty.clone())); 581 self.infer_expr(self.body.body_expr, &Expectation::has_type(self.return_ty.clone()));
577 } 582 }
578 583
579 fn resolve_into_iter_item(&self) -> Option<TypeAlias> { 584 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..54765da35 100644
--- a/crates/ra_hir/src/ty/infer/coerce.rs
+++ b/crates/ra_hir/src/ty/infer/coerce.rs
@@ -4,13 +4,12 @@
4//! 4//!
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See: https://doc.rust-lang.org/nomicon/coercions.html
6 6
7use hir_def::resolver::Resolver; 7use hir_def::{lang_item::LangItemTarget, resolver::Resolver};
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use test_utils::tested_by; 9use test_utils::tested_by;
10 10
11use crate::{ 11use 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};
@@ -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 }
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index 20a7e9352..663ff9435 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -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 }
@@ -250,7 +255,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
250 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), 255 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()),
251 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { 256 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| {
252 self.write_field_resolution(tgt_expr, field); 257 self.write_field_resolution(tgt_expr, field);
253 field.ty(self.db).subst(&a_ty.parameters) 258 self.db.field_types(s.id.into())[field.id]
259 .clone()
260 .subst(&a_ty.parameters)
254 }), 261 }),
255 _ => None, 262 _ => None,
256 }, 263 },
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/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 75c552569..a39beb2a0 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -14,8 +14,9 @@ use hir_def::{
14 path::{GenericArg, PathSegment}, 14 path::{GenericArg, PathSegment},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, GenericDefId, 17 AdtId, GenericDefId, LocalStructFieldId, VariantId,
18}; 18};
19use ra_arena::map::ArenaMap;
19 20
20use super::{ 21use super::{
21 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 22 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
@@ -29,7 +30,7 @@ use crate::{
29 }, 30 },
30 util::make_mut_slice, 31 util::make_mut_slice,
31 Const, Enum, EnumVariant, Function, GenericDef, ImplBlock, ModuleDef, Path, Static, Struct, 32 Const, Enum, EnumVariant, Function, GenericDef, ImplBlock, ModuleDef, Path, Static, Struct,
32 StructField, Trait, TypeAlias, Union, VariantDef, 33 Trait, TypeAlias, Union,
33}; 34};
34 35
35// 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
@@ -549,16 +550,23 @@ pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSi
549 } 550 }
550} 551}
551 552
552/// Build the type of a specific field of a struct or enum variant. 553/// Build the type of all specific fields of a struct or enum variant.
553pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { 554pub(crate) fn field_types_query(
554 let parent_def = field.parent_def(db); 555 db: &impl HirDatabase,
555 let resolver = match parent_def { 556 variant_id: VariantId,
556 VariantDef::Struct(it) => it.id.resolver(db), 557) -> Arc<ArenaMap<LocalStructFieldId, Ty>> {
557 VariantDef::EnumVariant(it) => it.parent.id.resolver(db), 558 let (resolver, var_data) = match variant_id {
559 VariantId::StructId(it) => (it.resolver(db), db.struct_data(it.0).variant_data.clone()),
560 VariantId::EnumVariantId(it) => (
561 it.parent.resolver(db),
562 db.enum_data(it.parent).variants[it.local_id].variant_data.clone(),
563 ),
558 }; 564 };
559 let var_data = parent_def.variant_data(db); 565 let mut res = ArenaMap::default();
560 let type_ref = &var_data.fields().unwrap()[field.id].type_ref; 566 for (field_id, field_data) in var_data.fields().iter() {
561 Ty::from_hir(db, &resolver, type_ref) 567 res.insert(field_id, Ty::from_hir(db, &resolver, &field_data.type_ref))
568 }
569 Arc::new(res)
562} 570}
563 571
564/// This query exists only to be used when resolving short-hand associated types 572/// This query exists only to be used when resolving short-hand associated types
@@ -622,10 +630,10 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) ->
622} 630}
623 631
624fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { 632fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
625 let data = def.data(db); 633 let data = db.function_data(def.id);
626 let resolver = def.id.resolver(db); 634 let resolver = def.id.resolver(db);
627 let params = data.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); 635 let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
628 let ret = Ty::from_hir(db, &resolver, data.ret_type()); 636 let ret = Ty::from_hir(db, &resolver, &data.ret_type);
629 FnSig::from_params_and_return(params, ret) 637 FnSig::from_params_and_return(params, ret)
630} 638}
631 639
@@ -639,18 +647,18 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
639 647
640/// Build the declared type of a const. 648/// Build the declared type of a const.
641fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { 649fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty {
642 let data = def.data(db); 650 let data = db.const_data(def.id);
643 let resolver = def.id.resolver(db); 651 let resolver = def.id.resolver(db);
644 652
645 Ty::from_hir(db, &resolver, data.type_ref()) 653 Ty::from_hir(db, &resolver, &data.type_ref)
646} 654}
647 655
648/// Build the declared type of a static. 656/// Build the declared type of a static.
649fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { 657fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty {
650 let data = def.data(db); 658 let data = db.static_data(def.id);
651 let resolver = def.id.resolver(db); 659 let resolver = def.id.resolver(db);
652 660
653 Ty::from_hir(db, &resolver, data.type_ref()) 661 Ty::from_hir(db, &resolver, &data.type_ref)
654} 662}
655 663
656/// Build the declared type of a static. 664/// Build the declared type of a static.
@@ -696,10 +704,7 @@ impl From<Option<BuiltinFloat>> for Uncertain<FloatTy> {
696 704
697fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { 705fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
698 let struct_data = db.struct_data(def.id.into()); 706 let struct_data = db.struct_data(def.id.into());
699 let fields = match struct_data.variant_data.fields() { 707 let fields = struct_data.variant_data.fields();
700 Some(fields) => fields,
701 None => panic!("fn_sig_for_struct_constructor called on unit struct"),
702 };
703 let resolver = def.id.resolver(db); 708 let resolver = def.id.resolver(db);
704 let params = fields 709 let params = fields
705 .iter() 710 .iter()
@@ -712,7 +717,7 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
712/// Build the type of a tuple struct constructor. 717/// Build the type of a tuple struct constructor.
713fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 718fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
714 let struct_data = db.struct_data(def.id.into()); 719 let struct_data = db.struct_data(def.id.into());
715 if struct_data.variant_data.fields().is_none() { 720 if struct_data.variant_data.is_unit() {
716 return type_for_adt(db, def); // Unit struct 721 return type_for_adt(db, def); // Unit struct
717 } 722 }
718 let generics = db.generic_params(def.id.into()); 723 let generics = db.generic_params(def.id.into());
@@ -722,10 +727,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
722 727
723fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { 728fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig {
724 let var_data = def.variant_data(db); 729 let var_data = def.variant_data(db);
725 let fields = match var_data.fields() { 730 let fields = var_data.fields();
726 Some(fields) => fields,
727 None => panic!("fn_sig_for_enum_variant_constructor called for unit variant"),
728 };
729 let resolver = def.parent.id.resolver(db); 731 let resolver = def.parent.id.resolver(db);
730 let params = fields 732 let params = fields
731 .iter() 733 .iter()
@@ -740,7 +742,7 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant)
740/// Build the type of a tuple enum variant constructor. 742/// Build the type of a tuple enum variant constructor.
741fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { 743fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
742 let var_data = def.variant_data(db); 744 let var_data = def.variant_data(db);
743 if var_data.fields().is_none() { 745 if var_data.is_unit() {
744 return type_for_adt(db, def.parent_enum(db)); // Unit variant 746 return type_for_adt(db, def.parent_enum(db)); // Unit variant
745 } 747 }
746 let generics = db.generic_params(def.parent_enum(db).id.into()); 748 let generics = db.generic_params(def.parent_enum(db).id.into());
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 64adb814d..caa5f5f74 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -5,7 +5,7 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::resolver::Resolver; 8use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef};
9use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
10 10
11use crate::{ 11use crate::{
@@ -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
@@ -233,7 +242,7 @@ fn iterate_trait_method_candidates<T>(
233 .chain(traits_from_env) 242 .chain(traits_from_env)
234 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from)); 243 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from));
235 'traits: for t in traits { 244 'traits: for t in traits {
236 let data = t.trait_data(db); 245 let data = db.trait_data(t.id);
237 246
238 // we'll be lazy about checking whether the type implements the 247 // 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 248 // trait, but if we find out it doesn't, we'll skip the rest of the
@@ -291,9 +300,9 @@ fn is_valid_candidate(
291) -> bool { 300) -> bool {
292 match item { 301 match item {
293 AssocItem::Function(m) => { 302 AssocItem::Function(m) => {
294 let data = m.data(db); 303 let data = db.function_data(m.id);
295 name.map_or(true, |name| data.name() == name) 304 name.map_or(true, |name| data.name == *name)
296 && (data.has_self_param() || mode == LookupMode::Path) 305 && (data.has_self_param || mode == LookupMode::Path)
297 } 306 }
298 AssocItem::Const(c) => { 307 AssocItem::Const(c) => {
299 name.map_or(true, |name| Some(name) == c.name(db).as_ref()) 308 name.map_or(true, |name| Some(name) == c.name(db).as_ref())
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]
4860fn infer_builtin_macros_file() {
4861 assert_snapshot!(
4862 infer(r#"
4863#[rustc_builtin_macro]
4864macro_rules! file {() => {}}
4865
4866fn 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]
4879fn infer_builtin_macros_column() {
4880 assert_snapshot!(
4881 infer(r#"
4882#[rustc_builtin_macro]
4883macro_rules! column {() => {}}
4884
4885fn 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
4use chalk_ir::{cast::Cast, family::ChalkIr}; 4use chalk_ir::{cast::Cast, family::ChalkIr};
5use log::debug; 5use log::debug;
6use ra_db::salsa; 6use ra_db::{impl_intern_key, salsa};
7use ra_prof::profile; 7use ra_prof::profile;
8use rustc_hash::FxHashSet; 8use 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)]
309pub struct GlobalImplId(salsa::InternId);
310impl_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)]
325pub struct AssocTyValueId(salsa::InternId);
326impl_intern_key!(AssocTyValueId);
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 88785f305..1a93e5e50 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};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11 11
12use hir_def::lang_item::LangItemTarget;
12use hir_expand::name; 13use hir_expand::name;
13 14
14use ra_db::salsa::{InternId, InternKey}; 15use ra_db::salsa::{InternId, InternKey};
@@ -18,7 +19,7 @@ use crate::{
18 db::HirDatabase, 19 db::HirDatabase,
19 ty::display::HirDisplay, 20 ty::display::HirDisplay,
20 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, 21 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
21 Crate, GenericDef, HasBody, ImplBlock, Trait, TypeAlias, 22 Crate, GenericDef, ImplBlock, Trait, TypeAlias,
22}; 23};
23 24
24/// This represents a trait whose name we could not resolve. 25/// This represents a trait whose name we could not resolve.
@@ -714,7 +715,7 @@ fn closure_fn_trait_impl_datum(
714 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)?;
715 fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; 716 fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?;
716 717
717 let num_args: u16 = match &data.def.body(db)[data.expr] { 718 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
718 crate::expr::Expr::Lambda { args, .. } => args.len() as u16, 719 crate::expr::Expr::Lambda { args, .. } => args.len() as u16,
719 _ => { 720 _ => {
720 log::warn!("closure for closure type {:?} not found", data); 721 log::warn!("closure for closure type {:?} not found", data);
@@ -804,7 +805,7 @@ fn closure_fn_trait_output_assoc_ty_value(
804) -> Arc<AssociatedTyValue<ChalkIr>> { 805) -> Arc<AssociatedTyValue<ChalkIr>> {
805 let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); 806 let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db);
806 807
807 let num_args: u16 = match &data.def.body(db)[data.expr] { 808 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
808 crate::expr::Expr::Lambda { args, .. } => args.len() as u16, 809 crate::expr::Expr::Lambda { args, .. } => args.len() as u16,
809 _ => { 810 _ => {
810 log::warn!("closure for closure type {:?} not found", data); 811 log::warn!("closure for closure type {:?} not found", data);
@@ -832,9 +833,9 @@ fn closure_fn_trait_output_assoc_ty_value(
832} 833}
833 834
834fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { 835fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> {
835 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())?;
836 match target { 837 match target {
837 crate::lang_item::LangItemTarget::Trait(t) => Some(t), 838 LangItemTarget::TraitId(t) => Some(t.into()),
838 _ => None, 839 _ => None,
839 } 840 }
840} 841}
@@ -846,38 +847,38 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
846 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } 847 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
847} 848}
848 849
849impl From<chalk_ir::StructId> for crate::ids::TypeCtorId { 850impl From<chalk_ir::StructId> for crate::ty::TypeCtorId {
850 fn from(struct_id: chalk_ir::StructId) -> Self { 851 fn from(struct_id: chalk_ir::StructId) -> Self {
851 id_from_chalk(struct_id.0) 852 id_from_chalk(struct_id.0)
852 } 853 }
853} 854}
854 855
855impl From<crate::ids::TypeCtorId> for chalk_ir::StructId { 856impl From<crate::ty::TypeCtorId> for chalk_ir::StructId {
856 fn from(type_ctor_id: crate::ids::TypeCtorId) -> Self { 857 fn from(type_ctor_id: crate::ty::TypeCtorId) -> Self {
857 chalk_ir::StructId(id_to_chalk(type_ctor_id)) 858 chalk_ir::StructId(id_to_chalk(type_ctor_id))
858 } 859 }
859} 860}
860 861
861impl From<chalk_ir::ImplId> for crate::ids::GlobalImplId { 862impl From<chalk_ir::ImplId> for crate::ty::traits::GlobalImplId {
862 fn from(impl_id: chalk_ir::ImplId) -> Self { 863 fn from(impl_id: chalk_ir::ImplId) -> Self {
863 id_from_chalk(impl_id.0) 864 id_from_chalk(impl_id.0)
864 } 865 }
865} 866}
866 867
867impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId { 868impl From<crate::ty::traits::GlobalImplId> for chalk_ir::ImplId {
868 fn from(impl_id: crate::ids::GlobalImplId) -> Self { 869 fn from(impl_id: crate::ty::traits::GlobalImplId) -> Self {
869 chalk_ir::ImplId(id_to_chalk(impl_id)) 870 chalk_ir::ImplId(id_to_chalk(impl_id))
870 } 871 }
871} 872}
872 873
873impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId { 874impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ty::traits::AssocTyValueId {
874 fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { 875 fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self {
875 id_from_chalk(id.0) 876 id_from_chalk(id.0)
876 } 877 }
877} 878}
878 879
879impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { 880impl From<crate::ty::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId {
880 fn from(assoc_ty_value_id: crate::ids::AssocTyValueId) -> Self { 881 fn from(assoc_ty_value_id: crate::ty::traits::AssocTyValueId) -> Self {
881 chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) 882 chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id))
882 } 883 }
883} 884}