aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_arena/src/lib.rs10
-rw-r--r--crates/ra_cli/src/analysis_stats.rs13
-rw-r--r--crates/ra_hir/src/code_model.rs114
-rw-r--r--crates/ra_hir/src/code_model/src.rs37
-rw-r--r--crates/ra_hir/src/db.rs23
-rw-r--r--crates/ra_hir/src/expr.rs6
-rw-r--r--crates/ra_hir/src/from_source.rs11
-rw-r--r--crates/ra_hir/src/impl_block.rs52
-rw-r--r--crates/ra_hir/src/lib.rs10
-rw-r--r--crates/ra_hir/src/source_binder.rs14
-rw-r--r--crates/ra_hir/src/test_db.rs2
-rw-r--r--crates/ra_hir/src/ty.rs5
-rw-r--r--crates/ra_hir/src/ty/infer.rs14
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs13
-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.rs44
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs6
-rw-r--r--crates/ra_hir_def/src/adt.rs20
-rw-r--r--crates/ra_hir_def/src/body.rs31
-rw-r--r--crates/ra_hir_def/src/body/lower.rs3
-rw-r--r--crates/ra_hir_def/src/body/scope.rs6
-rw-r--r--crates/ra_hir_def/src/lang_item.rs5
-rw-r--r--crates/ra_hir_def/src/lib.rs23
-rw-r--r--crates/ra_hir_def/src/nameres.rs32
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs5
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs20
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs2
-rw-r--r--crates/ra_hir_def/src/path.rs2
-rw-r--r--crates/ra_hir_def/src/per_ns.rs5
-rw-r--r--crates/ra_hir_def/src/resolver.rs26
-rw-r--r--crates/ra_hir_def/src/trace.rs42
-rw-r--r--crates/ra_ide_api/src/change.rs2
-rw-r--r--crates/ra_ide_api/src/references/classify.rs10
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs8
-rw-r--r--crates/ra_project_model/src/lib.rs17
-rw-r--r--crates/ra_project_model/src/sysroot.rs6
37 files changed, 324 insertions, 357 deletions
diff --git a/crates/ra_arena/src/lib.rs b/crates/ra_arena/src/lib.rs
index 3ec8d3b60..fc0f7c12f 100644
--- a/crates/ra_arena/src/lib.rs
+++ b/crates/ra_arena/src/lib.rs
@@ -37,7 +37,7 @@ impl fmt::Display for RawId {
37} 37}
38 38
39#[derive(Clone, PartialEq, Eq)] 39#[derive(Clone, PartialEq, Eq)]
40pub struct Arena<ID: ArenaId, T> { 40pub struct Arena<ID, T> {
41 data: Vec<T>, 41 data: Vec<T>,
42 _ty: PhantomData<ID>, 42 _ty: PhantomData<ID>,
43} 43}
@@ -67,6 +67,12 @@ pub trait ArenaId {
67 fn into_raw(self) -> RawId; 67 fn into_raw(self) -> RawId;
68} 68}
69 69
70impl<ID, T> Arena<ID, T> {
71 pub const fn new() -> Arena<ID, T> {
72 Arena { data: Vec::new(), _ty: PhantomData }
73 }
74}
75
70impl<ID: ArenaId, T> Arena<ID, T> { 76impl<ID: ArenaId, T> Arena<ID, T> {
71 pub fn len(&self) -> usize { 77 pub fn len(&self) -> usize {
72 self.data.len() 78 self.data.len()
@@ -79,7 +85,7 @@ impl<ID: ArenaId, T> Arena<ID, T> {
79 self.data.push(value); 85 self.data.push(value);
80 ID::from_raw(id) 86 ID::from_raw(id)
81 } 87 }
82 pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> + ExactSizeIterator { 88 pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> + ExactSizeIterator + DoubleEndedIterator {
83 self.data.iter().enumerate().map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value)) 89 self.data.iter().enumerate().map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value))
84 } 90 }
85} 91}
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index 9cd21e4b6..c4eb28245 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -3,7 +3,7 @@
3use std::{collections::HashSet, fmt::Write, path::Path, time::Instant}; 3use std::{collections::HashSet, fmt::Write, path::Path, time::Instant};
4 4
5use ra_db::SourceDatabaseExt; 5use ra_db::SourceDatabaseExt;
6use ra_hir::{AssocItem, Crate, HasBodySource, HasSource, HirDisplay, ModuleDef, Ty, TypeWalk}; 6use ra_hir::{AssocItem, Crate, HasSource, HirDisplay, ModuleDef, Ty, TypeWalk};
7use ra_syntax::AstNode; 7use ra_syntax::AstNode;
8 8
9use crate::{Result, Verbosity}; 9use crate::{Result, Verbosity};
@@ -109,7 +109,7 @@ pub fn run(
109 } 109 }
110 let body = f.body(db); 110 let body = f.body(db);
111 let inference_result = f.infer(db); 111 let inference_result = f.infer(db);
112 for (expr_id, _) in body.exprs() { 112 for (expr_id, _) in body.exprs.iter() {
113 let ty = &inference_result[expr_id]; 113 let ty = &inference_result[expr_id];
114 num_exprs += 1; 114 num_exprs += 1;
115 if let Ty::Unknown = ty { 115 if let Ty::Unknown = ty {
@@ -128,15 +128,16 @@ pub fn run(
128 if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) { 128 if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
129 num_type_mismatches += 1; 129 num_type_mismatches += 1;
130 if verbosity.is_verbose() { 130 if verbosity.is_verbose() {
131 let src = f.expr_source(db, expr_id); 131 let src = f.body_source_map(db).expr_syntax(expr_id);
132 if let Some(src) = src { 132 if let Some(src) = src {
133 // FIXME: it might be nice to have a function (on Analysis?) that goes from Source<T> -> (LineCol, LineCol) directly 133 // FIXME: it might be nice to have a function (on Analysis?) that goes from Source<T> -> (LineCol, LineCol) directly
134 let original_file = src.file_id.original_file(db); 134 let original_file = src.file_id.original_file(db);
135 let path = db.file_relative_path(original_file); 135 let path = db.file_relative_path(original_file);
136 let line_index = host.analysis().file_line_index(original_file).unwrap(); 136 let line_index = host.analysis().file_line_index(original_file).unwrap();
137 let text_range = src 137 let text_range = src.value.either(
138 .value 138 |it| it.syntax_node_ptr().range(),
139 .either(|it| it.syntax().text_range(), |it| it.syntax().text_range()); 139 |it| it.syntax_node_ptr().range(),
140 );
140 let (start, end) = ( 141 let (start, end) = (
141 line_index.line_col(text_range.start()), 142 line_index.line_col(text_range.start()),
142 line_index.line_col(text_range.end()), 143 line_index.line_col(text_range.end()),
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index b3e2ff1c2..3f44a50c4 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -6,7 +6,6 @@ use std::sync::Arc;
6 6
7use hir_def::{ 7use hir_def::{
8 adt::VariantData, 8 adt::VariantData,
9 body::scope::ExprScopes,
10 builtin_type::BuiltinType, 9 builtin_type::BuiltinType,
11 docs::Documentation, 10 docs::Documentation,
12 per_ns::PerNs, 11 per_ns::PerNs,
@@ -28,7 +27,7 @@ use crate::{
28 db::{DefDatabase, HirDatabase}, 27 db::{DefDatabase, HirDatabase},
29 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
30 ty::{InferenceResult, Namespace, TraitRef}, 29 ty::{InferenceResult, Namespace, TraitRef},
31 Either, HasSource, Name, Source, Ty, 30 Either, Name, Source, Ty,
32}; 31};
33 32
34/// hir::Crate describes a single crate. It's the main interface with which 33/// hir::Crate describes a single crate. It's the main interface with which
@@ -62,7 +61,7 @@ impl Crate {
62 } 61 }
63 62
64 pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> { 63 pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> {
65 let module_id = db.crate_def_map(self.crate_id).root(); 64 let module_id = db.crate_def_map(self.crate_id).root;
66 Some(Module::new(self, module_id)) 65 Some(Module::new(self, module_id))
67 } 66 }
68 67
@@ -195,7 +194,7 @@ impl Module {
195 /// in the module tree of any target in `Cargo.toml`. 194 /// in the module tree of any target in `Cargo.toml`.
196 pub fn crate_root(self, db: &impl DefDatabase) -> Module { 195 pub fn crate_root(self, db: &impl DefDatabase) -> Module {
197 let def_map = db.crate_def_map(self.id.krate); 196 let def_map = db.crate_def_map(self.id.krate);
198 self.with_module_id(def_map.root()) 197 self.with_module_id(def_map.root)
199 } 198 }
200 199
201 /// Finds a child module with the specified name. 200 /// Finds a child module with the specified name.
@@ -302,11 +301,11 @@ pub enum FieldSource {
302 301
303impl StructField { 302impl StructField {
304 pub fn name(&self, db: &impl HirDatabase) -> Name { 303 pub fn name(&self, db: &impl HirDatabase) -> Name {
305 self.parent.variant_data(db).fields().unwrap()[self.id].name.clone() 304 self.parent.variant_data(db).fields()[self.id].name.clone()
306 } 305 }
307 306
308 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 307 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
309 db.type_for_field(*self) 308 db.field_types(self.parent.into())[self.id].clone()
310 } 309 }
311 310
312 pub fn parent_def(&self, _db: &impl HirDatabase) -> VariantDef { 311 pub fn parent_def(&self, _db: &impl HirDatabase) -> VariantDef {
@@ -336,8 +335,7 @@ impl Struct {
336 db.struct_data(self.id.into()) 335 db.struct_data(self.id.into())
337 .variant_data 336 .variant_data
338 .fields() 337 .fields()
339 .into_iter() 338 .iter()
340 .flat_map(|it| it.iter())
341 .map(|(id, _)| StructField { parent: self.into(), id }) 339 .map(|(id, _)| StructField { parent: self.into(), id })
342 .collect() 340 .collect()
343 } 341 }
@@ -346,8 +344,7 @@ impl Struct {
346 db.struct_data(self.id.into()) 344 db.struct_data(self.id.into())
347 .variant_data 345 .variant_data
348 .fields() 346 .fields()
349 .into_iter() 347 .iter()
350 .flat_map(|it| it.iter())
351 .find(|(_id, data)| data.name == *name) 348 .find(|(_id, data)| data.name == *name)
352 .map(|(id, _)| StructField { parent: self.into(), id }) 349 .map(|(id, _)| StructField { parent: self.into(), id })
353 } 350 }
@@ -444,8 +441,7 @@ impl EnumVariant {
444 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 441 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
445 self.variant_data(db) 442 self.variant_data(db)
446 .fields() 443 .fields()
447 .into_iter() 444 .iter()
448 .flat_map(|it| it.iter())
449 .map(|(id, _)| StructField { parent: self.into(), id }) 445 .map(|(id, _)| StructField { parent: self.into(), id })
450 .collect() 446 .collect()
451 } 447 }
@@ -453,8 +449,7 @@ impl EnumVariant {
453 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { 449 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
454 self.variant_data(db) 450 self.variant_data(db)
455 .fields() 451 .fields()
456 .into_iter() 452 .iter()
457 .flat_map(|it| it.iter())
458 .find(|(_id, data)| data.name == *name) 453 .find(|(_id, data)| data.name == *name)
459 .map(|(id, _)| StructField { parent: self.into(), id }) 454 .map(|(id, _)| StructField { parent: self.into(), id })
460 } 455 }
@@ -510,7 +505,7 @@ impl VariantDef {
510 } 505 }
511 } 506 }
512 507
513 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { 508 pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
514 match self { 509 match self {
515 VariantDef::Struct(it) => it.field(db, name), 510 VariantDef::Struct(it) => it.field(db, name),
516 VariantDef::EnumVariant(it) => it.field(db, name), 511 VariantDef::EnumVariant(it) => it.field(db, name),
@@ -560,52 +555,6 @@ impl DefWithBody {
560 } 555 }
561} 556}
562 557
563pub trait HasBody: Copy {
564 fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult>;
565 fn body(self, db: &impl HirDatabase) -> Arc<Body>;
566 fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap>;
567 fn expr_scopes(self, db: &impl HirDatabase) -> Arc<ExprScopes>;
568}
569
570impl<T> HasBody for T
571where
572 T: Into<DefWithBody> + Copy + HasSource,
573{
574 fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
575 db.infer(self.into())
576 }
577
578 fn body(self, db: &impl HirDatabase) -> Arc<Body> {
579 self.into().body(db)
580 }
581
582 fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
583 self.into().body_source_map(db)
584 }
585
586 fn expr_scopes(self, db: &impl HirDatabase) -> Arc<ExprScopes> {
587 self.into().expr_scopes(db)
588 }
589}
590
591impl HasBody for DefWithBody {
592 fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
593 db.infer(self)
594 }
595
596 fn body(self, db: &impl HirDatabase) -> Arc<Body> {
597 db.body(self.into())
598 }
599
600 fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
601 db.body_with_source_map(self.into()).1
602 }
603
604 fn expr_scopes(self, db: &impl HirDatabase) -> Arc<ExprScopes> {
605 db.expr_scopes(self.into())
606 }
607}
608
609#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 558#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
610pub struct Function { 559pub struct Function {
611 pub(crate) id: FunctionId, 560 pub(crate) id: FunctionId,
@@ -632,7 +581,7 @@ impl Function {
632 db.function_data(self.id).params.clone() 581 db.function_data(self.id).params.clone()
633 } 582 }
634 583
635 pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> { 584 pub fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
636 db.body_with_source_map(self.id.into()).1 585 db.body_with_source_map(self.id.into()).1
637 } 586 }
638 587
@@ -966,7 +915,7 @@ pub struct Local {
966 915
967impl Local { 916impl Local {
968 pub fn name(self, db: &impl HirDatabase) -> Option<Name> { 917 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
969 let body = self.parent.body(db); 918 let body = db.body(self.parent.into());
970 match &body[self.pat_id] { 919 match &body[self.pat_id] {
971 Pat::Bind { name, .. } => Some(name.clone()), 920 Pat::Bind { name, .. } => Some(name.clone()),
972 _ => None, 921 _ => None,
@@ -978,7 +927,7 @@ impl Local {
978 } 927 }
979 928
980 pub fn is_mut(self, db: &impl HirDatabase) -> bool { 929 pub fn is_mut(self, db: &impl HirDatabase) -> bool {
981 let body = self.parent.body(db); 930 let body = db.body(self.parent.into());
982 match &body[self.pat_id] { 931 match &body[self.pat_id] {
983 Pat::Bind { mode, .. } => match mode { 932 Pat::Bind { mode, .. } => match mode {
984 BindingAnnotation::Mutable | BindingAnnotation::RefMut => true, 933 BindingAnnotation::Mutable | BindingAnnotation::RefMut => true,
@@ -1002,7 +951,7 @@ impl Local {
1002 } 951 }
1003 952
1004 pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { 953 pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> {
1005 let source_map = self.parent.body_source_map(db); 954 let (_body, source_map) = db.body_with_source_map(self.parent.into());
1006 let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... 955 let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm...
1007 let root = src.file_syntax(db); 956 let root = src.file_syntax(db);
1008 src.map(|ast| ast.map(|it| it.cast().unwrap().to_node(&root), |it| it.to_node(&root))) 957 src.map(|ast| ast.map(|it| it.cast().unwrap().to_node(&root), |it| it.to_node(&root)))
@@ -1020,6 +969,41 @@ pub struct ImplBlock {
1020 pub(crate) id: ImplId, 969 pub(crate) id: ImplId,
1021} 970}
1022 971
972impl ImplBlock {
973 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
974 db.impl_data(self.id).target_trait.clone()
975 }
976
977 pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef {
978 db.impl_data(self.id).target_type.clone()
979 }
980
981 pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
982 Ty::from_hir(db, &self.id.resolver(db), &self.target_type(db))
983 }
984
985 pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
986 let target_ty = self.target_ty(db);
987 TraitRef::from_hir(db, &self.id.resolver(db), &self.target_trait(db)?, Some(target_ty))
988 }
989
990 pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> {
991 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
992 }
993
994 pub fn is_negative(&self, db: &impl DefDatabase) -> bool {
995 db.impl_data(self.id).is_negative
996 }
997
998 pub fn module(&self, db: &impl DefDatabase) -> Module {
999 self.id.module(db).into()
1000 }
1001
1002 pub fn krate(&self, db: &impl DefDatabase) -> Crate {
1003 Crate { crate_id: self.module(db).id.krate }
1004 }
1005}
1006
1023/// For IDE only 1007/// For IDE only
1024pub enum ScopeDef { 1008pub enum ScopeDef {
1025 ModuleDef(ModuleDef), 1009 ModuleDef(ModuleDef),
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index b9d21bdd7..a4e317c20 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -2,12 +2,11 @@
2 2
3use hir_def::{AstItemDef, HasChildSource, HasSource as _, Lookup, VariantId}; 3use hir_def::{AstItemDef, HasChildSource, HasSource as _, Lookup, VariantId};
4use hir_expand::either::Either; 4use hir_expand::either::Either;
5use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::ast;
6 6
7use crate::{ 7use crate::{
8 db::{DefDatabase, HirDatabase}, 8 db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef,
9 Const, Enum, EnumVariant, FieldSource, Function, HasBody, Import, MacroDef, Module, 9 Module, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
10 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
11}; 10};
12 11
13pub use hir_expand::Source; 12pub use hir_expand::Source;
@@ -109,6 +108,12 @@ impl HasSource for MacroDef {
109 Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) } 108 Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) }
110 } 109 }
111} 110}
111impl HasSource for ImplBlock {
112 type Ast = ast::ImplBlock;
113 fn source(self, db: &impl DefDatabase) -> Source<ast::ImplBlock> {
114 self.id.source(db)
115 }
116}
112impl HasSource for Import { 117impl HasSource for Import {
113 type Ast = Either<ast::UseTree, ast::ExternCrateItem>; 118 type Ast = Either<ast::UseTree, ast::ExternCrateItem>;
114 119
@@ -121,27 +126,3 @@ impl HasSource for Import {
121 src.with_value(ptr.map(|it| it.to_node(&root), |it| it.to_node(&root))) 126 src.with_value(ptr.map(|it| it.to_node(&root), |it| it.to_node(&root)))
122 } 127 }
123} 128}
124
125pub trait HasBodySource: HasBody + HasSource
126where
127 Self::Ast: AstNode,
128{
129 fn expr_source(
130 self,
131 db: &impl HirDatabase,
132 expr_id: crate::expr::ExprId,
133 ) -> Option<Source<Either<ast::Expr, ast::RecordField>>> {
134 let source_map = self.body_source_map(db);
135 let source_ptr = source_map.expr_syntax(expr_id)?;
136 let root = source_ptr.file_syntax(db);
137 let source = source_ptr.map(|ast| ast.map(|it| it.to_node(&root), |it| it.to_node(&root)));
138 Some(source)
139 }
140}
141
142impl<T> HasBodySource for T
143where
144 T: HasBody + HasSource,
145 T::Ast: AstNode,
146{
147}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index a9dab2d25..5084bbacf 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -2,6 +2,7 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use ra_arena::map::ArenaMap;
5use ra_db::salsa; 6use ra_db::salsa;
6 7
7use crate::{ 8use crate::{
@@ -11,15 +12,19 @@ use crate::{
11 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, 12 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef,
12 TypeCtor, 13 TypeCtor,
13 }, 14 },
14 Crate, DefWithBody, GenericDef, ImplBlock, StructField, Trait, 15 Crate, DefWithBody, GenericDef, ImplBlock, Trait,
15}; 16};
16 17
17pub use hir_def::db::{ 18pub use hir_def::{
18 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery, 19 db::{
19 DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery, 20 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery,
20 FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, 21 DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery,
21 LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery, 22 FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase,
22 StaticDataQuery, StructDataQuery, TraitDataQuery, TypeAliasDataQuery, 23 InternDatabaseStorage, LangItemQuery, ModuleLangItemsQuery, RawItemsQuery,
24 RawItemsWithSourceMapQuery, StaticDataQuery, StructDataQuery, TraitDataQuery,
25 TypeAliasDataQuery,
26 },
27 LocalStructFieldId, VariantId,
23}; 28};
24pub use hir_expand::db::{ 29pub use hir_expand::db::{
25 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 30 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -35,8 +40,8 @@ pub trait HirDatabase: DefDatabase {
35 #[salsa::invoke(crate::ty::type_for_def)] 40 #[salsa::invoke(crate::ty::type_for_def)]
36 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty; 41 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty;
37 42
38 #[salsa::invoke(crate::ty::type_for_field)] 43 #[salsa::invoke(crate::ty::field_types_query)]
39 fn type_for_field(&self, field: StructField) -> Ty; 44 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
40 45
41 #[salsa::invoke(crate::ty::callable_item_sig)] 46 #[salsa::invoke(crate::ty::callable_item_sig)]
42 fn callable_item_signature(&self, def: CallableDef) -> FnSig; 47 fn callable_item_signature(&self, def: CallableDef) -> FnSig;
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 6b703d8b4..43fedde7a 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -44,15 +44,15 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
44 pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) { 44 pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) {
45 let body = self.func.body(db); 45 let body = self.func.body(db);
46 46
47 for e in body.exprs() { 47 for e in body.exprs.iter() {
48 if let (id, Expr::RecordLit { path, fields, spread }) = e { 48 if let (id, Expr::RecordLit { path, fields, spread }) = e {
49 self.validate_record_literal(id, path, fields, *spread, db); 49 self.validate_record_literal(id, path, fields, *spread, db);
50 } 50 }
51 } 51 }
52 52
53 let body_expr = &body[body.body_expr()]; 53 let body_expr = &body[body.body_expr];
54 if let Expr::Block { statements: _, tail: Some(t) } = body_expr { 54 if let Expr::Block { statements: _, tail: Some(t) } = body_expr {
55 self.validate_results_in_tail_expr(body.body_expr(), *t, db); 55 self.validate_results_in_tail_expr(body.body_expr, *t, db);
56 } 56 }
57 } 57 }
58 58
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index f506bba70..1e7c22774 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -9,9 +9,9 @@ use ra_syntax::{
9 9
10use crate::{ 10use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, 12 AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock,
13 ImplBlock, Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct, 13 Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct, StructField, Trait,
14 StructField, Trait, TypeAlias, Union, VariantDef, 14 TypeAlias, Union, VariantDef,
15}; 15};
16 16
17pub trait FromSource: Sized { 17pub trait FromSource: Sized {
@@ -200,8 +200,7 @@ impl FromSource for StructField {
200 variant_def 200 variant_def
201 .variant_data(db) 201 .variant_data(db)
202 .fields() 202 .fields()
203 .into_iter() 203 .iter()
204 .flat_map(|it| it.iter())
205 .map(|(id, _)| StructField { parent: variant_def, id }) 204 .map(|(id, _)| StructField { parent: variant_def, id })
206 .find(|f| f.source(db) == src) 205 .find(|f| f.source(db) == src)
207 } 206 }
@@ -221,7 +220,7 @@ impl Local {
221 }; 220 };
222 Some(res) 221 Some(res)
223 })?; 222 })?;
224 let source_map = parent.body_source_map(db); 223 let (_body, source_map) = db.body_with_source_map(parent.into());
225 let src = src.map(ast::Pat::from); 224 let src = src.map(ast::Pat::from);
226 let pat_id = source_map.node_pat(src.as_ref())?; 225 let pat_id = source_map.node_pat(src.as_ref())?;
227 Some(Local { parent, pat_id }) 226 Some(Local { parent, pat_id })
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
deleted file mode 100644
index 334eeebac..000000000
--- a/crates/ra_hir/src/impl_block.rs
+++ /dev/null
@@ -1,52 +0,0 @@
1//! FIXME: write short doc here
2
3use hir_def::{resolver::HasResolver, type_ref::TypeRef, AstItemDef};
4use ra_syntax::ast;
5
6use crate::{
7 db::{AstDatabase, DefDatabase, HirDatabase},
8 ty::Ty,
9 AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef,
10};
11
12impl HasSource for ImplBlock {
13 type Ast = ast::ImplBlock;
14 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> {
15 self.id.source(db)
16 }
17}
18
19impl ImplBlock {
20 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
21 db.impl_data(self.id).target_trait.clone()
22 }
23
24 pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef {
25 db.impl_data(self.id).target_type.clone()
26 }
27
28 pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
29 Ty::from_hir(db, &self.id.resolver(db), &self.target_type(db))
30 }
31
32 pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
33 let target_ty = self.target_ty(db);
34 TraitRef::from_hir(db, &self.id.resolver(db), &self.target_trait(db)?, Some(target_ty))
35 }
36
37 pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> {
38 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
39 }
40
41 pub fn is_negative(&self, db: &impl DefDatabase) -> bool {
42 db.impl_data(self.id).is_negative
43 }
44
45 pub fn module(&self, db: &impl DefDatabase) -> Module {
46 self.id.module(db).into()
47 }
48
49 pub fn krate(&self, db: &impl DefDatabase) -> Crate {
50 Crate { crate_id: self.module(db).id.krate }
51 }
52}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 8c589c728..843ce6a88 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -32,7 +32,6 @@ pub mod db;
32pub mod source_binder; 32pub mod source_binder;
33 33
34mod ty; 34mod ty;
35mod impl_block;
36mod expr; 35mod expr;
37pub mod diagnostics; 36pub mod diagnostics;
38mod util; 37mod util;
@@ -49,11 +48,10 @@ mod marks;
49 48
50pub use crate::{ 49pub use crate::{
51 code_model::{ 50 code_model::{
52 src::{HasBodySource, HasSource}, 51 src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency,
53 Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Docs, Enum, 52 DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam,
54 EnumVariant, FieldSource, Function, GenericDef, GenericParam, HasAttrs, HasBody, ImplBlock, 53 HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef,
55 Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, 54 Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef,
56 StructField, Trait, TypeAlias, Union, VariantDef,
57 }, 55 },
58 expr::ExprScopes, 56 expr::ExprScopes,
59 from_source::FromSource, 57 from_source::FromSource,
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index cfc4bd326..31390bb7f 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -28,8 +28,7 @@ use crate::{
28 expr::{BodySourceMap, ExprScopes, ScopeId}, 28 expr::{BodySourceMap, ExprScopes, ScopeId},
29 ty::method_resolution::{self, implements_trait}, 29 ty::method_resolution::{self, implements_trait},
30 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, 30 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function,
31 GenericParam, HasBody, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, 31 GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias,
32 TypeAlias,
33}; 32};
34 33
35fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { 34fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> {
@@ -155,8 +154,8 @@ impl SourceAnalyzer {
155 ) -> SourceAnalyzer { 154 ) -> SourceAnalyzer {
156 let def_with_body = def_with_body_from_child_node(db, node); 155 let def_with_body = def_with_body_from_child_node(db, node);
157 if let Some(def) = def_with_body { 156 if let Some(def) = def_with_body {
158 let source_map = def.body_source_map(db); 157 let (_body, source_map) = db.body_with_source_map(def.into());
159 let scopes = def.expr_scopes(db); 158 let scopes = db.expr_scopes(def.into());
160 let scope = match offset { 159 let scope = match offset {
161 None => scope_for(&scopes, &source_map, node), 160 None => scope_for(&scopes, &source_map, node),
162 Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)), 161 Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)),
@@ -166,7 +165,7 @@ impl SourceAnalyzer {
166 resolver, 165 resolver,
167 body_owner: Some(def), 166 body_owner: Some(def),
168 body_source_map: Some(source_map), 167 body_source_map: Some(source_map),
169 infer: Some(def.infer(db)), 168 infer: Some(db.infer(def)),
170 scopes: Some(scopes), 169 scopes: Some(scopes),
171 file_id: node.file_id, 170 file_id: node.file_id,
172 } 171 }
@@ -216,6 +215,11 @@ impl SourceAnalyzer {
216 self.infer.as_ref()?.field_resolution(expr_id) 215 self.infer.as_ref()?.field_resolution(expr_id)
217 } 216 }
218 217
218 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> {
219 let expr_id = self.expr_id(&field.expr()?)?;
220 self.infer.as_ref()?.record_field_resolution(expr_id)
221 }
222
219 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { 223 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> {
220 let expr_id = self.expr_id(&record_lit.clone().into())?; 224 let expr_id = self.expr_id(&record_lit.clone().into())?;
221 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 225 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
diff --git a/crates/ra_hir/src/test_db.rs b/crates/ra_hir/src/test_db.rs
index 03c7ac155..efee2f658 100644
--- a/crates/ra_hir/src/test_db.rs
+++ b/crates/ra_hir/src/test_db.rs
@@ -80,7 +80,7 @@ impl TestDB {
80 let crate_graph = self.crate_graph(); 80 let crate_graph = self.crate_graph();
81 for krate in crate_graph.iter().next() { 81 for krate in crate_graph.iter().next() {
82 let crate_def_map = self.crate_def_map(krate); 82 let crate_def_map = self.crate_def_map(krate);
83 for module_id in crate_def_map.modules() { 83 for (module_id, _) in crate_def_map.modules.iter() {
84 let module_id = ModuleId { krate, module_id }; 84 let module_id = ModuleId { krate, module_id };
85 let module = crate::Module::from(module_id); 85 let module = crate::Module::from(module_id);
86 module.diagnostics( 86 module.diagnostics(
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 309bd2727..f62316c1f 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -30,8 +30,9 @@ pub(crate) use autoderef::autoderef;
30pub(crate) use infer::{infer_query, InferTy, InferenceResult}; 30pub(crate) use infer::{infer_query, InferTy, InferenceResult};
31pub use lower::CallableDef; 31pub use lower::CallableDef;
32pub(crate) use lower::{ 32pub(crate) use lower::{
33 callable_item_sig, generic_defaults_query, generic_predicates_for_param_query, 33 callable_item_sig, field_types_query, generic_defaults_query,
34 generic_predicates_query, type_for_def, type_for_field, Namespace, TypableDef, 34 generic_predicates_for_param_query, generic_predicates_query, type_for_def, Namespace,
35 TypableDef,
35}; 36};
36pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 37pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
37 38
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 471bdc387..ddc7d262a 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -44,8 +44,7 @@ use crate::{
44 db::HirDatabase, 44 db::HirDatabase,
45 expr::{BindingAnnotation, Body, ExprId, PatId}, 45 expr::{BindingAnnotation, Body, ExprId, PatId},
46 ty::infer::diagnostics::InferenceDiagnostic, 46 ty::infer::diagnostics::InferenceDiagnostic,
47 Adt, AssocItem, DefWithBody, FloatTy, Function, HasBody, IntTy, Path, StructField, Trait, 47 Adt, AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, Trait, VariantDef,
48 VariantDef,
49}; 48};
50 49
51macro_rules! ty_app { 50macro_rules! ty_app {
@@ -126,6 +125,8 @@ pub struct InferenceResult {
126 method_resolutions: FxHashMap<ExprId, Function>, 125 method_resolutions: FxHashMap<ExprId, Function>,
127 /// For each field access expr, records the field it resolves to. 126 /// For each field access expr, records the field it resolves to.
128 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>,
129 /// For each struct literal, records the variant it resolves to. 130 /// For each struct literal, records the variant it resolves to.
130 variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, 131 variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>,
131 /// For each associated item record what it resolves to 132 /// For each associated item record what it resolves to
@@ -143,6 +144,9 @@ impl InferenceResult {
143 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { 144 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> {
144 self.field_resolutions.get(&expr).copied() 145 self.field_resolutions.get(&expr).copied()
145 } 146 }
147 pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructField> {
148 self.record_field_resolutions.get(&expr).copied()
149 }
146 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantDef> { 150 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantDef> {
147 self.variant_resolutions.get(&id.into()).copied() 151 self.variant_resolutions.get(&id.into()).copied()
148 } 152 }
@@ -216,7 +220,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
216 coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), 220 coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver),
217 db, 221 db,
218 owner, 222 owner,
219 body: owner.body(db), 223 body: db.body(owner.into()),
220 resolver, 224 resolver,
221 } 225 }
222 } 226 }
@@ -565,7 +569,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
565 569
566 fn collect_fn(&mut self, data: &FunctionData) { 570 fn collect_fn(&mut self, data: &FunctionData) {
567 let body = Arc::clone(&self.body); // avoid borrow checker problem 571 let body = Arc::clone(&self.body); // avoid borrow checker problem
568 for (type_ref, pat) in data.params.iter().zip(body.params()) { 572 for (type_ref, pat) in data.params.iter().zip(body.params.iter()) {
569 let ty = self.make_ty(type_ref); 573 let ty = self.make_ty(type_ref);
570 574
571 self.infer_pat(*pat, &ty, BindingMode::default()); 575 self.infer_pat(*pat, &ty, BindingMode::default());
@@ -574,7 +578,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
574 } 578 }
575 579
576 fn infer_body(&mut self) { 580 fn infer_body(&mut self) {
577 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()));
578 } 582 }
579 583
580 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 4ea038d99..54765da35 100644
--- a/crates/ra_hir/src/ty/infer/coerce.rs
+++ b/crates/ra_hir/src/ty/infer/coerce.rs
@@ -245,14 +245,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
245 ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), 245 ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1),
246 ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), 246 ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2),
247 ) if struct1 == struct2 => { 247 ) if struct1 == struct2 => {
248 let fields = struct1.fields(self.db); 248 let field_tys = self.db.field_types(struct1.id.into());
249 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()?;
250 253
251 // Get the generic parameter involved in the last field. 254 // Get the generic parameter involved in the last field.
252 let unsize_generic_index = { 255 let unsize_generic_index = {
253 let mut index = None; 256 let mut index = None;
254 let mut multiple_param = false; 257 let mut multiple_param = false;
255 last_field.ty(self.db).walk(&mut |ty| match ty { 258 field_tys[last_field_id].walk(&mut |ty| match ty {
256 &Ty::Param { idx, .. } => { 259 &Ty::Param { idx, .. } => {
257 if index.is_none() { 260 if index.is_none() {
258 index = Some(idx); 261 index = Some(idx);
@@ -271,8 +274,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
271 274
272 // Check other fields do not involve it. 275 // Check other fields do not involve it.
273 let mut multiple_used = false; 276 let mut multiple_used = false;
274 prev_fields.iter().for_each(|field| { 277 fields.for_each(|(field_id, _data)| {
275 field.ty(self.db).walk(&mut |ty| match ty { 278 field_tys[field_id].walk(&mut |ty| match ty {
276 &Ty::Param { idx, .. } if idx == unsize_generic_index => { 279 &Ty::Param { idx, .. } if idx == unsize_generic_index => {
277 multiple_used = true 280 multiple_used = true
278 } 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 2272510e8..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
@@ -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/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 9efdc53c4..1a93e5e50 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -19,7 +19,7 @@ use crate::{
19 db::HirDatabase, 19 db::HirDatabase,
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, GenericDef, HasBody, ImplBlock, Trait, TypeAlias, 22 Crate, GenericDef, 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.
@@ -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);
@@ -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);
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 20e9a1eb5..c9f30923e 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -95,7 +95,7 @@ fn lower_enum(
95 name: var.name().map(|it| it.as_name()), 95 name: var.name().map(|it| it.as_name()),
96 variant_data: Arc::new(VariantData::new(var.kind())), 96 variant_data: Arc::new(VariantData::new(var.kind())),
97 }, 97 },
98 ) 98 );
99 } 99 }
100} 100}
101 101
@@ -109,10 +109,18 @@ impl VariantData {
109 } 109 }
110 } 110 }
111 111
112 pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> { 112 pub fn fields(&self) -> &Arena<LocalStructFieldId, StructFieldData> {
113 const EMPTY: &Arena<LocalStructFieldId, StructFieldData> = &Arena::new();
113 match &self { 114 match &self {
114 VariantData::Record(fields) | VariantData::Tuple(fields) => Some(fields), 115 VariantData::Record(fields) | VariantData::Tuple(fields) => fields,
115 _ => None, 116 _ => EMPTY,
117 }
118 }
119
120 pub fn is_unit(&self) -> bool {
121 match self {
122 VariantData::Unit => true,
123 _ => false,
116 } 124 }
117 } 125 }
118} 126}
@@ -160,7 +168,7 @@ fn lower_struct(
160 name: Name::new_tuple_field(i), 168 name: Name::new_tuple_field(i),
161 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 169 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
162 }, 170 },
163 ) 171 );
164 } 172 }
165 StructKind::Tuple 173 StructKind::Tuple
166 } 174 }
@@ -172,7 +180,7 @@ fn lower_struct(
172 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 180 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
173 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 181 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
174 }, 182 },
175 ) 183 );
176 } 184 }
177 StructKind::Record 185 StructKind::Record
178 } 186 }
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index c06997cf1..d77ccb272 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -1,4 +1,5 @@
1//! FIXME: write short doc here 1//! Defines `Body`: a lowered representation of bodies of functions, statics and
2//! consts.
2mod lower; 3mod lower;
3pub mod scope; 4pub mod scope;
4 5
@@ -20,7 +21,7 @@ use crate::{
20 DefWithBodyId, HasModule, HasSource, Lookup, ModuleId, 21 DefWithBodyId, HasModule, HasSource, Lookup, ModuleId,
21}; 22};
22 23
23pub struct Expander { 24struct Expander {
24 crate_def_map: Arc<CrateDefMap>, 25 crate_def_map: Arc<CrateDefMap>,
25 current_file_id: HirFileId, 26 current_file_id: HirFileId,
26 hygiene: Hygiene, 27 hygiene: Hygiene,
@@ -28,7 +29,7 @@ pub struct Expander {
28} 29}
29 30
30impl Expander { 31impl Expander {
31 pub fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { 32 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 33 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 34 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 35 Expander { crate_def_map, current_file_id, hygiene, module }
@@ -101,17 +102,17 @@ impl Drop for Mark {
101/// The body of an item (function, const etc.). 102/// The body of an item (function, const etc.).
102#[derive(Debug, Eq, PartialEq)] 103#[derive(Debug, Eq, PartialEq)]
103pub struct Body { 104pub struct Body {
104 exprs: Arena<ExprId, Expr>, 105 pub exprs: Arena<ExprId, Expr>,
105 pats: Arena<PatId, Pat>, 106 pub pats: Arena<PatId, Pat>,
106 /// The patterns for the function's parameters. While the parameter types are 107 /// The patterns for the function's parameters. While the parameter types are
107 /// part of the function signature, the patterns are not (they don't change 108 /// part of the function signature, the patterns are not (they don't change
108 /// the external type of the function). 109 /// the external type of the function).
109 /// 110 ///
110 /// If this `Body` is for the body of a constant, this will just be 111 /// If this `Body` is for the body of a constant, this will just be
111 /// empty. 112 /// empty.
112 params: Vec<PatId>, 113 pub params: Vec<PatId>,
113 /// The `ExprId` of the actual body expression. 114 /// The `ExprId` of the actual body expression.
114 body_expr: ExprId, 115 pub body_expr: ExprId,
115} 116}
116 117
117pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 118pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
@@ -182,22 +183,6 @@ impl Body {
182 ) -> (Body, BodySourceMap) { 183 ) -> (Body, BodySourceMap) {
183 lower::lower(db, expander, params, body) 184 lower::lower(db, expander, params, body)
184 } 185 }
185
186 pub fn params(&self) -> &[PatId] {
187 &self.params
188 }
189
190 pub fn body_expr(&self) -> ExprId {
191 self.body_expr
192 }
193
194 pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> {
195 self.exprs.iter()
196 }
197
198 pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> {
199 self.pats.iter()
200 }
201} 186}
202 187
203impl Index<ExprId> for Body { 188impl Index<ExprId> for Body {
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index f4640dfa4..331736cb2 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -1,4 +1,5 @@
1//! FIXME: write short doc here 1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2//! representation.
2 3
3use hir_expand::{ 4use hir_expand::{
4 either::Either, 5 either::Either,
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 20d707bc4..625aa39dd 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! Name resolution for expressions.
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_expand::name::Name; 4use hir_expand::name::Name;
@@ -54,8 +54,8 @@ impl ExprScopes {
54 let mut scopes = 54 let mut scopes =
55 ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; 55 ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() };
56 let root = scopes.root_scope(); 56 let root = scopes.root_scope();
57 scopes.add_params_bindings(body, root, body.params()); 57 scopes.add_params_bindings(body, root, &body.params);
58 compute_expr_scopes(body.body_expr(), body, &mut scopes, root); 58 compute_expr_scopes(body.body_expr, body, &mut scopes, root);
59 scopes 59 scopes
60 } 60 }
61 61
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index 3b9fb0328..f15c23db9 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -39,8 +39,9 @@ impl LangItems {
39 let crate_def_map = db.crate_def_map(krate); 39 let crate_def_map = db.crate_def_map(krate);
40 40
41 crate_def_map 41 crate_def_map
42 .modules() 42 .modules
43 .filter_map(|module_id| db.module_lang_items(ModuleId { krate, module_id })) 43 .iter()
44 .filter_map(|(module_id, _)| db.module_lang_items(ModuleId { krate, module_id }))
44 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v)))); 45 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v))));
45 46
46 Arc::new(lang_items) 47 Arc::new(lang_items)
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index f63c3dd64..8e8c2d749 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -192,12 +192,6 @@ pub struct LocalEnumVariantId(RawId);
192impl_arena_id!(LocalEnumVariantId); 192impl_arena_id!(LocalEnumVariantId);
193 193
194#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 194#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
195pub enum VariantId {
196 EnumVariantId(EnumVariantId),
197 StructId(StructId),
198}
199
200#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
201pub struct StructFieldId { 195pub struct StructFieldId {
202 pub parent: VariantId, 196 pub parent: VariantId,
203 pub local_id: LocalStructFieldId, 197 pub local_id: LocalStructFieldId,
@@ -437,6 +431,13 @@ impl_froms!(
437 ImplId 431 ImplId
438); 432);
439 433
434#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
435pub enum VariantId {
436 EnumVariantId(EnumVariantId),
437 StructId(StructId),
438}
439impl_froms!(VariantId: EnumVariantId, StructId);
440
440trait Intern { 441trait Intern {
441 type ID; 442 type ID;
442 fn intern(self, db: &impl db::DefDatabase) -> Self::ID; 443 fn intern(self, db: &impl db::DefDatabase) -> Self::ID;
@@ -481,6 +482,16 @@ impl HasModule for ConstLoc {
481 } 482 }
482} 483}
483 484
485impl HasModule for AdtId {
486 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
487 match self {
488 AdtId::StructId(it) => it.0.module(db),
489 AdtId::UnionId(it) => it.0.module(db),
490 AdtId::EnumId(it) => it.module(db),
491 }
492 }
493}
494
484impl HasModule for StaticLoc { 495impl HasModule for StaticLoc {
485 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { 496 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
486 self.container 497 self.container
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index 5919771b0..2359386c2 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -80,16 +80,16 @@ use crate::{
80/// Contains all top-level defs from a macro-expanded crate 80/// Contains all top-level defs from a macro-expanded crate
81#[derive(Debug, PartialEq, Eq)] 81#[derive(Debug, PartialEq, Eq)]
82pub struct CrateDefMap { 82pub struct CrateDefMap {
83 krate: CrateId, 83 pub root: LocalModuleId,
84 edition: Edition, 84 pub modules: Arena<LocalModuleId, ModuleData>,
85 pub(crate) krate: CrateId,
85 /// The prelude module for this crate. This either comes from an import 86 /// The prelude module for this crate. This either comes from an import
86 /// marked with the `prelude_import` attribute, or (in the normal case) from 87 /// marked with the `prelude_import` attribute, or (in the normal case) from
87 /// a dependency (`std` or `core`). 88 /// a dependency (`std` or `core`).
88 prelude: Option<ModuleId>, 89 pub(crate) prelude: Option<ModuleId>,
89 extern_prelude: FxHashMap<Name, ModuleDefId>, 90 pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>,
90 root: LocalModuleId,
91 modules: Arena<LocalModuleId, ModuleData>,
92 91
92 edition: Edition,
93 diagnostics: Vec<DefDiagnostic>, 93 diagnostics: Vec<DefDiagnostic>,
94} 94}
95 95
@@ -229,22 +229,6 @@ impl CrateDefMap {
229 Arc::new(def_map) 229 Arc::new(def_map)
230 } 230 }
231 231
232 pub fn krate(&self) -> CrateId {
233 self.krate
234 }
235
236 pub fn root(&self) -> LocalModuleId {
237 self.root
238 }
239
240 pub fn prelude(&self) -> Option<ModuleId> {
241 self.prelude
242 }
243
244 pub fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDefId> {
245 &self.extern_prelude
246 }
247
248 pub fn add_diagnostics( 232 pub fn add_diagnostics(
249 &self, 233 &self,
250 db: &impl DefDatabase, 234 db: &impl DefDatabase,
@@ -254,10 +238,6 @@ impl CrateDefMap {
254 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) 238 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
255 } 239 }
256 240
257 pub fn modules(&self) -> impl Iterator<Item = LocalModuleId> + '_ {
258 self.modules.iter().map(|(id, _data)| id)
259 }
260
261 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ { 241 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
262 self.modules 242 self.modules
263 .iter() 243 .iter()
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index df01a20e1..41becf8df 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -1,4 +1,7 @@
1//! FIXME: write short doc here 1//! The core of the module-level name resolution algorithm.
2//!
3//! `DefCollector::collect` contains the fixed-point iteration loop which
4//! resolves imports and expands macros.
2 5
3use hir_expand::{ 6use hir_expand::{
4 builtin_macro::find_builtin_macro, 7 builtin_macro::find_builtin_macro,
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 2ec84f2cc..401af031c 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -22,7 +22,8 @@ use ra_syntax::{
22use test_utils::tested_by; 22use test_utils::tested_by;
23 23
24use crate::{ 24use crate::{
25 attr::Attrs, db::DefDatabase, path::Path, FileAstId, HirFileId, LocalImportId, Source, 25 attr::Attrs, db::DefDatabase, path::Path, trace::Trace, FileAstId, HirFileId, LocalImportId,
26 Source,
26}; 27};
27 28
28/// `RawItems` is a set of top-level items in a file (except for impls). 29/// `RawItems` is a set of top-level items in a file (except for impls).
@@ -48,10 +49,6 @@ pub struct ImportSourceMap {
48type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; 49type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
49 50
50impl ImportSourceMap { 51impl ImportSourceMap {
51 fn insert(&mut self, import: LocalImportId, ptr: ImportSourcePtr) {
52 self.map.insert(import, ptr)
53 }
54
55 pub fn get(&self, import: LocalImportId) -> ImportSourcePtr { 52 pub fn get(&self, import: LocalImportId) -> ImportSourcePtr {
56 self.map[import].clone() 53 self.map[import].clone()
57 } 54 }
@@ -72,7 +69,7 @@ impl RawItems {
72 let mut collector = RawItemsCollector { 69 let mut collector = RawItemsCollector {
73 raw_items: RawItems::default(), 70 raw_items: RawItems::default(),
74 source_ast_id_map: db.ast_id_map(file_id), 71 source_ast_id_map: db.ast_id_map(file_id),
75 source_map: ImportSourceMap::default(), 72 imports: Trace::new(),
76 file_id, 73 file_id,
77 hygiene: Hygiene::new(db, file_id), 74 hygiene: Hygiene::new(db, file_id),
78 }; 75 };
@@ -83,7 +80,11 @@ impl RawItems {
83 collector.process_module(None, item_list); 80 collector.process_module(None, item_list);
84 } 81 }
85 } 82 }
86 (Arc::new(collector.raw_items), Arc::new(collector.source_map)) 83 let mut raw_items = collector.raw_items;
84 let (arena, map) = collector.imports.into_arena_and_map();
85 raw_items.imports = arena;
86 let source_map = ImportSourceMap { map };
87 (Arc::new(raw_items), Arc::new(source_map))
87 } 88 }
88 89
89 pub(super) fn items(&self) -> &[RawItem] { 90 pub(super) fn items(&self) -> &[RawItem] {
@@ -207,8 +208,8 @@ pub(super) struct ImplData {
207 208
208struct RawItemsCollector { 209struct RawItemsCollector {
209 raw_items: RawItems, 210 raw_items: RawItems,
211 imports: Trace<LocalImportId, ImportData, ImportSourcePtr>,
210 source_ast_id_map: Arc<AstIdMap>, 212 source_ast_id_map: Arc<AstIdMap>,
211 source_map: ImportSourceMap,
212 file_id: HirFileId, 213 file_id: HirFileId,
213 hygiene: Hygiene, 214 hygiene: Hygiene,
214} 215}
@@ -392,8 +393,7 @@ impl RawItemsCollector {
392 data: ImportData, 393 data: ImportData,
393 source: ImportSourcePtr, 394 source: ImportSourcePtr,
394 ) { 395 ) {
395 let import = self.raw_items.imports.alloc(data); 396 let import = self.imports.alloc(|| source, || data);
396 self.source_map.insert(import, source);
397 self.push_item(current_module, attrs, RawItemKind::Import(import)) 397 self.push_item(current_module, attrs, RawItemKind::Import(import))
398 } 398 }
399 399
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index f0b86af7c..f502f1cb3 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -25,7 +25,7 @@ fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> {
25 25
26fn render_crate_def_map(map: &CrateDefMap) -> String { 26fn render_crate_def_map(map: &CrateDefMap) -> String {
27 let mut buf = String::new(); 27 let mut buf = String::new();
28 go(&mut buf, map, "\ncrate", map.root()); 28 go(&mut buf, map, "\ncrate", map.root);
29 return buf.trim().to_string(); 29 return buf.trim().to_string();
30 30
31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) { 31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) {
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 7b2723d57..0e606fd0e 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -195,7 +195,7 @@ impl Path {
195 } 195 }
196 196
197 /// Converts an `ast::NameRef` into a single-identifier `Path`. 197 /// Converts an `ast::NameRef` into a single-identifier `Path`.
198 pub fn from_name_ref(name_ref: &ast::NameRef) -> Path { 198 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
199 name_ref.as_name().into() 199 name_ref.as_name().into()
200 } 200 }
201 201
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs
index 06ef6c9fc..00e866bf9 100644
--- a/crates/ra_hir_def/src/per_ns.rs
+++ b/crates/ra_hir_def/src/per_ns.rs
@@ -1,4 +1,7 @@
1//! FIXME: write short doc here 1//! In rust, it is possible to have a value, a type and a macro with the same
2//! name without conflicts.
3//!
4//! `PerNs` (per namespace) captures this.
2 5
3use hir_expand::MacroDefId; 6use hir_expand::MacroDefId;
4 7
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 7182b8a4d..95b3c926d 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -18,8 +18,8 @@ use crate::{
18 path::{Path, PathKind}, 18 path::{Path, PathKind},
19 per_ns::PerNs, 19 per_ns::PerNs,
20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, 20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
21 GenericDefId, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, 21 GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId,
22 TraitId, TypeAliasId, 22 StructId, TraitId, TypeAliasId,
23}; 23};
24 24
25#[derive(Debug, Clone, Default)] 25#[derive(Debug, Clone, Default)]
@@ -29,20 +29,20 @@ pub struct Resolver {
29 29
30// FIXME how to store these best 30// FIXME how to store these best
31#[derive(Debug, Clone)] 31#[derive(Debug, Clone)]
32pub(crate) struct ModuleItemMap { 32struct ModuleItemMap {
33 crate_def_map: Arc<CrateDefMap>, 33 crate_def_map: Arc<CrateDefMap>,
34 module_id: LocalModuleId, 34 module_id: LocalModuleId,
35} 35}
36 36
37#[derive(Debug, Clone)] 37#[derive(Debug, Clone)]
38pub(crate) struct ExprScope { 38struct ExprScope {
39 owner: DefWithBodyId, 39 owner: DefWithBodyId,
40 expr_scopes: Arc<ExprScopes>, 40 expr_scopes: Arc<ExprScopes>,
41 scope_id: ScopeId, 41 scope_id: ScopeId,
42} 42}
43 43
44#[derive(Debug, Clone)] 44#[derive(Debug, Clone)]
45pub(crate) enum Scope { 45enum Scope {
46 /// All the items and imported names of a module 46 /// All the items and imported names of a module
47 ModuleScope(ModuleItemMap), 47 ModuleScope(ModuleItemMap),
48 /// Brings the generic parameters of an item into scope 48 /// Brings the generic parameters of an item into scope
@@ -321,7 +321,7 @@ impl Resolver {
321 let mut traits = FxHashSet::default(); 321 let mut traits = FxHashSet::default();
322 for scope in &self.scopes { 322 for scope in &self.scopes {
323 if let Scope::ModuleScope(m) = scope { 323 if let Scope::ModuleScope(m) = scope {
324 if let Some(prelude) = m.crate_def_map.prelude() { 324 if let Some(prelude) = m.crate_def_map.prelude {
325 let prelude_def_map = db.crate_def_map(prelude.krate); 325 let prelude_def_map = db.crate_def_map(prelude.krate);
326 traits.extend(prelude_def_map[prelude.module_id].scope.traits()); 326 traits.extend(prelude_def_map[prelude.module_id].scope.traits());
327 } 327 }
@@ -340,7 +340,7 @@ impl Resolver {
340 } 340 }
341 341
342 pub fn krate(&self) -> Option<CrateId> { 342 pub fn krate(&self) -> Option<CrateId> {
343 self.module().map(|t| t.0.krate()) 343 self.module().map(|t| t.0.krate)
344 } 344 }
345 345
346 pub fn where_predicates_in_scope<'a>( 346 pub fn where_predicates_in_scope<'a>(
@@ -395,10 +395,10 @@ impl Scope {
395 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { 395 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
396 f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); 396 f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_)));
397 }); 397 });
398 m.crate_def_map.extern_prelude().iter().for_each(|(name, &def)| { 398 m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| {
399 f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into()))); 399 f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into())));
400 }); 400 });
401 if let Some(prelude) = m.crate_def_map.prelude() { 401 if let Some(prelude) = m.crate_def_map.prelude {
402 let prelude_def_map = db.crate_def_map(prelude.krate); 402 let prelude_def_map = db.crate_def_map(prelude.krate);
403 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| { 403 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| {
404 f(name.clone(), ScopeDef::PerNs(res.def)); 404 f(name.clone(), ScopeDef::PerNs(res.def));
@@ -503,13 +503,7 @@ impl HasResolver for TraitId {
503impl<T: Into<AdtId>> HasResolver for T { 503impl<T: Into<AdtId>> HasResolver for T {
504 fn resolver(self, db: &impl DefDatabase) -> Resolver { 504 fn resolver(self, db: &impl DefDatabase) -> Resolver {
505 let def = self.into(); 505 let def = self.into();
506 let module = match def { 506 def.module(db)
507 AdtId::StructId(it) => it.0.module(db),
508 AdtId::UnionId(it) => it.0.module(db),
509 AdtId::EnumId(it) => it.module(db),
510 };
511
512 module
513 .resolver(db) 507 .resolver(db)
514 .push_generic_params_scope(db, def.into()) 508 .push_generic_params_scope(db, def.into())
515 .push_scope(Scope::AdtScope(def)) 509 .push_scope(Scope::AdtScope(def))
diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs
index fc26f5a48..2bcd707bc 100644
--- a/crates/ra_hir_def/src/trace.rs
+++ b/crates/ra_hir_def/src/trace.rs
@@ -12,38 +12,48 @@
12use ra_arena::{map::ArenaMap, Arena, ArenaId, RawId}; 12use ra_arena::{map::ArenaMap, Arena, ArenaId, RawId};
13 13
14pub(crate) struct Trace<ID: ArenaId, T, V> { 14pub(crate) struct Trace<ID: ArenaId, T, V> {
15 for_arena: bool, 15 arena: Option<Arena<ID, T>>,
16 arena: Arena<ID, T>, 16 map: Option<ArenaMap<ID, V>>,
17 map: ArenaMap<ID, V>,
18 len: u32, 17 len: u32,
19} 18}
20 19
21impl<ID: ra_arena::ArenaId, T, V> Trace<ID, T, V> { 20impl<ID: ra_arena::ArenaId + Copy, T, V> Trace<ID, T, V> {
21 pub(crate) fn new() -> Trace<ID, T, V> {
22 Trace { arena: Some(Arena::default()), map: Some(ArenaMap::default()), len: 0 }
23 }
24
22 pub(crate) fn new_for_arena() -> Trace<ID, T, V> { 25 pub(crate) fn new_for_arena() -> Trace<ID, T, V> {
23 Trace { for_arena: true, arena: Arena::default(), map: ArenaMap::default(), len: 0 } 26 Trace { arena: Some(Arena::default()), map: None, len: 0 }
24 } 27 }
25 28
26 pub(crate) fn new_for_map() -> Trace<ID, T, V> { 29 pub(crate) fn new_for_map() -> Trace<ID, T, V> {
27 Trace { for_arena: false, arena: Arena::default(), map: ArenaMap::default(), len: 0 } 30 Trace { arena: None, map: Some(ArenaMap::default()), len: 0 }
28 } 31 }
29 32
30 pub(crate) fn alloc(&mut self, value: impl Fn() -> V, data: impl Fn() -> T) { 33 pub(crate) fn alloc(&mut self, value: impl FnOnce() -> V, data: impl FnOnce() -> T) -> ID {
31 if self.for_arena { 34 let id = if let Some(arena) = &mut self.arena {
32 self.arena.alloc(data()); 35 arena.alloc(data())
33 } else { 36 } else {
34 let id = ID::from_raw(RawId::from(self.len)); 37 let id = ID::from_raw(RawId::from(self.len));
35 self.len += 1; 38 self.len += 1;
36 self.map.insert(id, value()); 39 id
40 };
41
42 if let Some(map) = &mut self.map {
43 map.insert(id, value());
37 } 44 }
45 id
46 }
47
48 pub(crate) fn into_arena(mut self) -> Arena<ID, T> {
49 self.arena.take().unwrap()
38 } 50 }
39 51
40 pub(crate) fn into_arena(self) -> Arena<ID, T> { 52 pub(crate) fn into_map(mut self) -> ArenaMap<ID, V> {
41 assert!(self.for_arena); 53 self.map.take().unwrap()
42 self.arena
43 } 54 }
44 55
45 pub(crate) fn into_map(self) -> ArenaMap<ID, V> { 56 pub(crate) fn into_arena_and_map(mut self) -> (Arena<ID, T>, ArenaMap<ID, V>) {
46 assert!(!self.for_arena); 57 (self.arena.take().unwrap(), self.map.take().unwrap())
47 self.map
48 } 58 }
49} 59}
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 8a05b287f..0f692460d 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -324,7 +324,7 @@ impl RootDatabase {
324 hir::db::ExprScopesQuery 324 hir::db::ExprScopesQuery
325 hir::db::InferQuery 325 hir::db::InferQuery
326 hir::db::TypeForDefQuery 326 hir::db::TypeForDefQuery
327 hir::db::TypeForFieldQuery 327 hir::db::FieldTypesQuery
328 hir::db::CallableItemSignatureQuery 328 hir::db::CallableItemSignatureQuery
329 hir::db::GenericPredicatesQuery 329 hir::db::GenericPredicatesQuery
330 hir::db::GenericDefaultsQuery 330 hir::db::GenericDefaultsQuery
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs
index 4a4b030f8..cab06dea9 100644
--- a/crates/ra_ide_api/src/references/classify.rs
+++ b/crates/ra_ide_api/src/references/classify.rs
@@ -1,6 +1,6 @@
1//! Functions that are used to classify an element from its definition or reference. 1//! Functions that are used to classify an element from its definition or reference.
2 2
3use hir::{FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; 3use hir::{FromSource, Module, ModuleSource, PathResolution, Source, SourceAnalyzer};
4use ra_prof::profile; 4use ra_prof::profile;
5use ra_syntax::{ast, match_ast, AstNode}; 5use ra_syntax::{ast, match_ast, AstNode};
6use test_utils::tested_by; 6use test_utils::tested_by;
@@ -140,12 +140,8 @@ pub(crate) fn classify_name_ref(
140 140
141 if let Some(record_field) = ast::RecordField::cast(parent.clone()) { 141 if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
142 tested_by!(goto_definition_works_for_record_fields); 142 tested_by!(goto_definition_works_for_record_fields);
143 if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { 143 if let Some(field_def) = analyzer.resolve_record_field(&record_field) {
144 let variant_def = analyzer.resolve_record_literal(&record_lit)?; 144 return Some(from_struct_field(db, field_def));
145 let hir_path = Path::from_name_ref(name_ref.value);
146 let hir_name = hir_path.as_ident()?;
147 let field = variant_def.field(db, hir_name)?;
148 return Some(from_struct_field(db, field));
149 } 145 }
150 } 146 }
151 147
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index c128e608d..351997dcd 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -54,11 +54,13 @@ struct TargetData {
54 name: String, 54 name: String,
55 root: PathBuf, 55 root: PathBuf,
56 kind: TargetKind, 56 kind: TargetKind,
57 is_proc_macro: bool,
57} 58}
58 59
59#[derive(Debug, Clone, Copy, PartialEq, Eq)] 60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum TargetKind { 61pub enum TargetKind {
61 Bin, 62 Bin,
63 /// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
62 Lib, 64 Lib,
63 Example, 65 Example,
64 Test, 66 Test,
@@ -74,6 +76,7 @@ impl TargetKind {
74 "test" => TargetKind::Test, 76 "test" => TargetKind::Test,
75 "bench" => TargetKind::Bench, 77 "bench" => TargetKind::Bench,
76 "example" => TargetKind::Example, 78 "example" => TargetKind::Example,
79 "proc-macro" => TargetKind::Lib,
77 _ if kind.contains("lib") => TargetKind::Lib, 80 _ if kind.contains("lib") => TargetKind::Lib,
78 _ => continue, 81 _ => continue,
79 }; 82 };
@@ -123,6 +126,9 @@ impl Target {
123 pub fn kind(self, ws: &CargoWorkspace) -> TargetKind { 126 pub fn kind(self, ws: &CargoWorkspace) -> TargetKind {
124 ws.targets[self].kind 127 ws.targets[self].kind
125 } 128 }
129 pub fn is_proc_macro(self, ws: &CargoWorkspace) -> bool {
130 ws.targets[self].is_proc_macro
131 }
126} 132}
127 133
128impl CargoWorkspace { 134impl CargoWorkspace {
@@ -155,11 +161,13 @@ impl CargoWorkspace {
155 let pkg_data = &mut packages[pkg]; 161 let pkg_data = &mut packages[pkg];
156 pkg_by_id.insert(id, pkg); 162 pkg_by_id.insert(id, pkg);
157 for meta_tgt in meta_pkg.targets { 163 for meta_tgt in meta_pkg.targets {
164 let is_proc_macro = meta_tgt.kind.as_slice() == &["proc-macro"];
158 let tgt = targets.alloc(TargetData { 165 let tgt = targets.alloc(TargetData {
159 pkg, 166 pkg,
160 name: meta_tgt.name, 167 name: meta_tgt.name,
161 root: meta_tgt.src_path.clone(), 168 root: meta_tgt.src_path.clone(),
162 kind: TargetKind::new(meta_tgt.kind.as_slice()), 169 kind: TargetKind::new(meta_tgt.kind.as_slice()),
170 is_proc_macro,
163 }); 171 });
164 pkg_data.targets.push(tgt); 172 pkg_data.targets.push(tgt);
165 } 173 }
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 638ca2f8b..55ff4d6ef 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -211,6 +211,8 @@ impl ProjectWorkspace {
211 let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied()); 211 let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied());
212 let liballoc = sysroot.alloc().and_then(|it| sysroot_crates.get(&it).copied()); 212 let liballoc = sysroot.alloc().and_then(|it| sysroot_crates.get(&it).copied());
213 let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied()); 213 let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied());
214 let libproc_macro =
215 sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
214 216
215 let mut pkg_to_lib_crate = FxHashMap::default(); 217 let mut pkg_to_lib_crate = FxHashMap::default();
216 let mut pkg_crates = FxHashMap::default(); 218 let mut pkg_crates = FxHashMap::default();
@@ -237,6 +239,21 @@ impl ProjectWorkspace {
237 lib_tgt = Some(crate_id); 239 lib_tgt = Some(crate_id);
238 pkg_to_lib_crate.insert(pkg, crate_id); 240 pkg_to_lib_crate.insert(pkg, crate_id);
239 } 241 }
242 if tgt.is_proc_macro(&cargo) {
243 if let Some(proc_macro) = libproc_macro {
244 if let Err(_) = crate_graph.add_dep(
245 crate_id,
246 "proc_macro".into(),
247 proc_macro,
248 ) {
249 log::error!(
250 "cyclic dependency on proc_macro for {}",
251 pkg.name(&cargo)
252 )
253 }
254 }
255 }
256
240 pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); 257 pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
241 } 258 }
242 } 259 }
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index bec9439d7..10ca391b6 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -39,6 +39,10 @@ impl Sysroot {
39 self.by_name("std") 39 self.by_name("std")
40 } 40 }
41 41
42 pub fn proc_macro(&self) -> Option<SysrootCrate> {
43 self.by_name("proc_macro")
44 }
45
42 pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a { 46 pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
43 self.crates.iter().map(|(id, _data)| id) 47 self.crates.iter().map(|(id, _data)| id)
44 } 48 }
@@ -74,7 +78,7 @@ impl Sysroot {
74 } 78 }
75 } 79 }
76 if let Some(alloc) = sysroot.by_name("alloc") { 80 if let Some(alloc) = sysroot.by_name("alloc") {
77 if let Some(core) = sysroot.by_name("core") { 81 if let Some(core) = sysroot.core() {
78 sysroot.crates[alloc].deps.push(core); 82 sysroot.crates[alloc].deps.push(core);
79 } 83 }
80 } 84 }