aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/adt.rs20
-rw-r--r--crates/ra_hir_def/src/attr.rs1
-rw-r--r--crates/ra_hir_def/src/body.rs72
-rw-r--r--crates/ra_hir_def/src/body/lower.rs58
-rw-r--r--crates/ra_hir_def/src/data.rs37
-rw-r--r--crates/ra_hir_def/src/diagnostics.rs2
-rw-r--r--crates/ra_hir_def/src/expr.rs33
-rw-r--r--crates/ra_hir_def/src/lang_item.rs5
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs14
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs2
-rw-r--r--crates/ra_hir_def/src/nameres/tests/incremental.rs6
-rw-r--r--crates/ra_hir_def/src/path.rs5
12 files changed, 131 insertions, 124 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index be4b0accb..7c0d93691 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -4,7 +4,6 @@ use std::sync::Arc;
4 4
5use either::Either; 5use either::Either;
6use hir_expand::{ 6use hir_expand::{
7 hygiene::Hygiene,
8 name::{AsName, Name}, 7 name::{AsName, Name},
9 InFile, 8 InFile,
10}; 9};
@@ -13,7 +12,7 @@ use ra_prof::profile;
13use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
14 13
15use crate::{ 14use crate::{
16 attr::Attrs, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, 15 body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
17 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, 16 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId,
18 LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, 17 LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
19}; 18};
@@ -125,8 +124,9 @@ fn lower_enum(
125 124
126impl VariantData { 125impl VariantData {
127 fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self { 126 fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self {
127 let mut expander = CfgExpander::new(db, flavor.file_id, module_id.krate);
128 let mut trace = Trace::new_for_arena(); 128 let mut trace = Trace::new_for_arena();
129 match lower_struct(db, &mut trace, &flavor, module_id) { 129 match lower_struct(db, &mut expander, &mut trace, &flavor) {
130 StructKind::Tuple => VariantData::Tuple(trace.into_arena()), 130 StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
131 StructKind::Record => VariantData::Record(trace.into_arena()), 131 StructKind::Record => VariantData::Record(trace.into_arena()),
132 StructKind::Unit => VariantData::Unit, 132 StructKind::Unit => VariantData::Unit,
@@ -178,8 +178,9 @@ impl HasChildSource for VariantId {
178 it.lookup(db).container.module(db), 178 it.lookup(db).container.module(db),
179 ), 179 ),
180 }; 180 };
181 let mut expander = CfgExpander::new(db, src.file_id, module_id.krate);
181 let mut trace = Trace::new_for_map(); 182 let mut trace = Trace::new_for_map();
182 lower_struct(db, &mut trace, &src, module_id); 183 lower_struct(db, &mut expander, &mut trace, &src);
183 src.with_value(trace.into_map()) 184 src.with_value(trace.into_map())
184 } 185 }
185} 186}
@@ -193,16 +194,15 @@ pub enum StructKind {
193 194
194fn lower_struct( 195fn lower_struct(
195 db: &dyn DefDatabase, 196 db: &dyn DefDatabase,
197 expander: &mut CfgExpander,
196 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, 198 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
197 ast: &InFile<ast::StructKind>, 199 ast: &InFile<ast::StructKind>,
198 module_id: ModuleId,
199) -> StructKind { 200) -> StructKind {
200 let crate_graph = db.crate_graph();
201 match &ast.value { 201 match &ast.value {
202 ast::StructKind::Tuple(fl) => { 202 ast::StructKind::Tuple(fl) => {
203 for (i, fd) in fl.fields().enumerate() { 203 for (i, fd) in fl.fields().enumerate() {
204 let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id)); 204 let attrs = expander.parse_attrs(&fd);
205 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { 205 if !expander.is_cfg_enabled(&attrs) {
206 continue; 206 continue;
207 } 207 }
208 208
@@ -219,8 +219,8 @@ fn lower_struct(
219 } 219 }
220 ast::StructKind::Record(fl) => { 220 ast::StructKind::Record(fl) => {
221 for fd in fl.fields() { 221 for fd in fl.fields() {
222 let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id)); 222 let attrs = expander.parse_attrs(&fd);
223 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { 223 if !expander.is_cfg_enabled(&attrs) {
224 continue; 224 continue;
225 } 225 }
226 226
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 7b0c506b1..2f2e3e5ba 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -93,6 +93,7 @@ impl Attrs {
93 } 93 }
94 94
95 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { 95 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
96 // FIXME: handle cfg_attr :-)
96 self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) 97 self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false))
97 } 98 }
98} 99}
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 5f9d53ecb..eafaf48c1 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -9,11 +9,14 @@ use drop_bomb::DropBomb;
9use either::Either; 9use either::Either;
10use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId}; 10use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId};
11use ra_arena::{map::ArenaMap, Arena}; 11use ra_arena::{map::ArenaMap, Arena};
12use ra_cfg::CfgOptions;
13use ra_db::CrateId;
12use ra_prof::profile; 14use ra_prof::profile;
13use ra_syntax::{ast, AstNode, AstPtr}; 15use ra_syntax::{ast, AstNode, AstPtr};
14use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
15 17
16use crate::{ 18use crate::{
19 attr::Attrs,
17 db::DefDatabase, 20 db::DefDatabase,
18 expr::{Expr, ExprId, Pat, PatId}, 21 expr::{Expr, ExprId, Pat, PatId},
19 item_scope::BuiltinShadowMode, 22 item_scope::BuiltinShadowMode,
@@ -24,25 +27,59 @@ use crate::{
24 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, 27 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
25}; 28};
26 29
30/// A subser of Exander that only deals with cfg attributes. We only need it to
31/// avoid cyclic queries in crate def map during enum processing.
32pub(crate) struct CfgExpander {
33 cfg_options: CfgOptions,
34 hygiene: Hygiene,
35}
36
27pub(crate) struct Expander { 37pub(crate) struct Expander {
38 cfg_expander: CfgExpander,
28 crate_def_map: Arc<CrateDefMap>, 39 crate_def_map: Arc<CrateDefMap>,
29 current_file_id: HirFileId, 40 current_file_id: HirFileId,
30 hygiene: Hygiene,
31 ast_id_map: Arc<AstIdMap>, 41 ast_id_map: Arc<AstIdMap>,
32 module: ModuleId, 42 module: ModuleId,
33 recursive_limit: usize, 43 recursive_limit: usize,
34} 44}
35 45
46impl CfgExpander {
47 pub(crate) fn new(
48 db: &dyn DefDatabase,
49 current_file_id: HirFileId,
50 krate: CrateId,
51 ) -> CfgExpander {
52 let hygiene = Hygiene::new(db.upcast(), current_file_id);
53 let cfg_options = db.crate_graph()[krate].cfg_options.clone();
54 CfgExpander { cfg_options, hygiene }
55 }
56
57 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
58 Attrs::new(owner, &self.hygiene)
59 }
60
61 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
62 attrs.is_cfg_enabled(&self.cfg_options)
63 }
64}
65
36impl Expander { 66impl Expander {
37 pub(crate) fn new( 67 pub(crate) fn new(
38 db: &dyn DefDatabase, 68 db: &dyn DefDatabase,
39 current_file_id: HirFileId, 69 current_file_id: HirFileId,
40 module: ModuleId, 70 module: ModuleId,
41 ) -> Expander { 71 ) -> Expander {
72 let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
42 let crate_def_map = db.crate_def_map(module.krate); 73 let crate_def_map = db.crate_def_map(module.krate);
43 let hygiene = Hygiene::new(db.upcast(), current_file_id);
44 let ast_id_map = db.ast_id_map(current_file_id); 74 let ast_id_map = db.ast_id_map(current_file_id);
45 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module, recursive_limit: 0 } 75 Expander {
76 cfg_expander,
77 crate_def_map,
78 current_file_id,
79 ast_id_map,
80 module,
81 recursive_limit: 0,
82 }
46 } 83 }
47 84
48 pub(crate) fn enter_expand<T: ast::AstNode>( 85 pub(crate) fn enter_expand<T: ast::AstNode>(
@@ -75,7 +112,7 @@ impl Expander {
75 ast_id_map: mem::take(&mut self.ast_id_map), 112 ast_id_map: mem::take(&mut self.ast_id_map),
76 bomb: DropBomb::new("expansion mark dropped"), 113 bomb: DropBomb::new("expansion mark dropped"),
77 }; 114 };
78 self.hygiene = Hygiene::new(db.upcast(), file_id); 115 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
79 self.current_file_id = file_id; 116 self.current_file_id = file_id;
80 self.ast_id_map = db.ast_id_map(file_id); 117 self.ast_id_map = db.ast_id_map(file_id);
81 self.recursive_limit += 1; 118 self.recursive_limit += 1;
@@ -91,7 +128,7 @@ impl Expander {
91 } 128 }
92 129
93 pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { 130 pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
94 self.hygiene = Hygiene::new(db.upcast(), mark.file_id); 131 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id);
95 self.current_file_id = mark.file_id; 132 self.current_file_id = mark.file_id;
96 self.ast_id_map = mem::take(&mut mark.ast_id_map); 133 self.ast_id_map = mem::take(&mut mark.ast_id_map);
97 self.recursive_limit -= 1; 134 self.recursive_limit -= 1;
@@ -102,8 +139,16 @@ impl Expander {
102 InFile { file_id: self.current_file_id, value } 139 InFile { file_id: self.current_file_id, value }
103 } 140 }
104 141
142 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
143 self.cfg_expander.parse_attrs(owner)
144 }
145
146 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
147 self.cfg_expander.is_cfg_enabled(attrs)
148 }
149
105 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 150 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
106 Path::from_src(path, &self.hygiene) 151 Path::from_src(path, &self.cfg_expander.hygiene)
107 } 152 }
108 153
109 fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { 154 fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
@@ -142,7 +187,7 @@ pub struct Body {
142 pub item_scope: ItemScope, 187 pub item_scope: ItemScope,
143} 188}
144 189
145pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 190pub type ExprPtr = AstPtr<ast::Expr>;
146pub type ExprSource = InFile<ExprPtr>; 191pub type ExprSource = InFile<ExprPtr>;
147 192
148pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; 193pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
@@ -236,11 +281,11 @@ impl Index<PatId> for Body {
236 281
237impl BodySourceMap { 282impl BodySourceMap {
238 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { 283 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
239 self.expr_map_back[expr] 284 self.expr_map_back[expr].clone()
240 } 285 }
241 286
242 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> { 287 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> {
243 let src = node.map(|it| Either::Left(AstPtr::new(it))); 288 let src = node.map(|it| AstPtr::new(it));
244 self.expr_map.get(&src).cloned() 289 self.expr_map.get(&src).cloned()
245 } 290 }
246 291
@@ -249,13 +294,8 @@ impl BodySourceMap {
249 self.expansions.get(&src).cloned() 294 self.expansions.get(&src).cloned()
250 } 295 }
251 296
252 pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
253 let src = node.map(|it| Either::Right(AstPtr::new(it)));
254 self.expr_map.get(&src).cloned()
255 }
256
257 pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> { 297 pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
258 self.pat_map_back[pat] 298 self.pat_map_back[pat].clone()
259 } 299 }
260 300
261 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> { 301 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
@@ -264,6 +304,6 @@ impl BodySourceMap {
264 } 304 }
265 305
266 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> { 306 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
267 self.field_map[&(expr, field)] 307 self.field_map[&(expr, field)].clone()
268 } 308 }
269} 309}
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index e1b08d48f..c057dc8f2 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -2,9 +2,7 @@
2//! representation. 2//! representation.
3 3
4use either::Either; 4use either::Either;
5
6use hir_expand::{ 5use hir_expand::{
7 hygiene::Hygiene,
8 name::{name, AsName, Name}, 6 name::{name, AsName, Name},
9 MacroDefId, MacroDefKind, 7 MacroDefId, MacroDefKind,
10}; 8};
@@ -18,10 +16,8 @@ use ra_syntax::{
18}; 16};
19use test_utils::tested_by; 17use test_utils::tested_by;
20 18
21use super::{ExprSource, PatSource};
22use crate::{ 19use crate::{
23 adt::StructKind, 20 adt::StructKind,
24 attr::Attrs,
25 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, 21 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax},
26 builtin_type::{BuiltinFloat, BuiltinInt}, 22 builtin_type::{BuiltinFloat, BuiltinInt},
27 db::DefDatabase, 23 db::DefDatabase,
@@ -31,12 +27,13 @@ use crate::{
31 }, 27 },
32 item_scope::BuiltinShadowMode, 28 item_scope::BuiltinShadowMode,
33 path::GenericArgs, 29 path::GenericArgs,
34 path::Path,
35 type_ref::{Mutability, TypeRef}, 30 type_ref::{Mutability, TypeRef},
36 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, HasModule, Intern, 31 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
37 ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 32 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
38}; 33};
39 34
35use super::{ExprSource, PatSource};
36
40pub(super) fn lower( 37pub(super) fn lower(
41 db: &dyn DefDatabase, 38 db: &dyn DefDatabase,
42 def: DefWithBodyId, 39 def: DefWithBodyId,
@@ -104,9 +101,8 @@ impl ExprCollector<'_> {
104 } 101 }
105 102
106 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 103 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
107 let ptr = Either::Left(ptr);
108 let src = self.expander.to_source(ptr); 104 let src = self.expander.to_source(ptr);
109 let id = self.make_expr(expr, Ok(src)); 105 let id = self.make_expr(expr, Ok(src.clone()));
110 self.source_map.expr_map.insert(src, id); 106 self.source_map.expr_map.insert(src, id);
111 id 107 id
112 } 108 }
@@ -115,13 +111,6 @@ impl ExprCollector<'_> {
115 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { 111 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
116 self.make_expr(expr, Err(SyntheticSyntax)) 112 self.make_expr(expr, Err(SyntheticSyntax))
117 } 113 }
118 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId {
119 let ptr = Either::Right(ptr);
120 let src = self.expander.to_source(ptr);
121 let id = self.make_expr(expr, Ok(src));
122 self.source_map.expr_map.insert(src, id);
123 id
124 }
125 fn empty_block(&mut self) -> ExprId { 114 fn empty_block(&mut self) -> ExprId {
126 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) 115 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None })
127 } 116 }
@@ -136,7 +125,7 @@ impl ExprCollector<'_> {
136 125
137 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { 126 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
138 let src = self.expander.to_source(ptr); 127 let src = self.expander.to_source(ptr);
139 let id = self.make_pat(pat, Ok(src)); 128 let id = self.make_pat(pat, Ok(src.clone()));
140 self.source_map.pat_map.insert(src, id); 129 self.source_map.pat_map.insert(src, id);
141 id 130 id
142 } 131 }
@@ -291,7 +280,7 @@ impl ExprCollector<'_> {
291 ast::Expr::ParenExpr(e) => { 280 ast::Expr::ParenExpr(e) => {
292 let inner = self.collect_expr_opt(e.expr()); 281 let inner = self.collect_expr_opt(e.expr());
293 // make the paren expr point to the inner expression as well 282 // make the paren expr point to the inner expression as well
294 let src = self.expander.to_source(Either::Left(syntax_ptr)); 283 let src = self.expander.to_source(syntax_ptr);
295 self.source_map.expr_map.insert(src, inner); 284 self.source_map.expr_map.insert(src, inner);
296 inner 285 inner
297 } 286 }
@@ -300,7 +289,6 @@ impl ExprCollector<'_> {
300 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 289 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
301 } 290 }
302 ast::Expr::RecordLit(e) => { 291 ast::Expr::RecordLit(e) => {
303 let crate_graph = self.db.crate_graph();
304 let path = e.path().and_then(|path| self.expander.parse_path(path)); 292 let path = e.path().and_then(|path| self.expander.parse_path(path));
305 let mut field_ptrs = Vec::new(); 293 let mut field_ptrs = Vec::new();
306 let record_lit = if let Some(nfl) = e.record_field_list() { 294 let record_lit = if let Some(nfl) = e.record_field_list() {
@@ -308,31 +296,17 @@ impl ExprCollector<'_> {
308 .fields() 296 .fields()
309 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 297 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
310 .filter_map(|field| { 298 .filter_map(|field| {
311 let module_id = ContainerId::DefWithBodyId(self.def).module(self.db); 299 let attrs = self.expander.parse_attrs(&field);
312 let attrs = Attrs::new( 300 if !self.expander.is_cfg_enabled(&attrs) {
313 &field,
314 &Hygiene::new(self.db.upcast(), self.expander.current_file_id),
315 );
316
317 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
318 return None; 301 return None;
319 } 302 }
303 let name = field.field_name()?.as_name();
320 304
321 Some(RecordLitField { 305 Some(RecordLitField {
322 name: field 306 name,
323 .name_ref() 307 expr: match field.expr() {
324 .map(|nr| nr.as_name()) 308 Some(e) => self.collect_expr(e),
325 .unwrap_or_else(Name::missing), 309 None => self.missing_expr(),
326 expr: if let Some(e) = field.expr() {
327 self.collect_expr(e)
328 } else if let Some(nr) = field.name_ref() {
329 // field shorthand
330 self.alloc_expr_field_shorthand(
331 Expr::Path(Path::from_name_ref(&nr)),
332 AstPtr::new(&field),
333 )
334 } else {
335 self.missing_expr()
336 }, 310 },
337 }) 311 })
338 }) 312 })
@@ -668,7 +642,9 @@ impl ExprCollector<'_> {
668 }); 642 });
669 fields.extend(iter); 643 fields.extend(iter);
670 644
671 Pat::Record { path, args: fields } 645 let ellipsis = record_field_pat_list.dotdot_token().is_some();
646
647 Pat::Record { path, args: fields, ellipsis }
672 } 648 }
673 ast::Pat::SlicePat(p) => { 649 ast::Pat::SlicePat(p) => {
674 let SlicePatComponents { prefix, slice, suffix } = p.components(); 650 let SlicePatComponents { prefix, slice, suffix } = p.components();
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index b8fbf0ed4..56a20c5bd 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -20,7 +20,7 @@ use crate::{
20 type_ref::{Mutability, TypeBound, TypeRef}, 20 type_ref::{Mutability, TypeBound, TypeRef},
21 visibility::RawVisibility, 21 visibility::RawVisibility,
22 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, 22 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
23 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 23 ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
24}; 24};
25 25
26#[derive(Debug, Clone, PartialEq, Eq)] 26#[derive(Debug, Clone, PartialEq, Eq)]
@@ -218,10 +218,17 @@ impl ImplData {
218 let mut items = Vec::new(); 218 let mut items = Vec::new();
219 219
220 if let Some(item_list) = src.value.item_list() { 220 if let Some(item_list) = src.value.item_list() {
221 items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); 221 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
222 items.extend(collect_impl_items(
223 db,
224 &mut expander,
225 item_list.impl_items(),
226 src.file_id,
227 id,
228 ));
222 items.extend(collect_impl_items_in_macros( 229 items.extend(collect_impl_items_in_macros(
223 db, 230 db,
224 module_id, 231 &mut expander,
225 &src.with_value(item_list), 232 &src.with_value(item_list),
226 id, 233 id,
227 )); 234 ));
@@ -268,18 +275,17 @@ impl ConstData {
268 275
269fn collect_impl_items_in_macros( 276fn collect_impl_items_in_macros(
270 db: &dyn DefDatabase, 277 db: &dyn DefDatabase,
271 module_id: ModuleId, 278 expander: &mut Expander,
272 impl_def: &InFile<ast::ItemList>, 279 impl_def: &InFile<ast::ItemList>,
273 id: ImplId, 280 id: ImplId,
274) -> Vec<AssocItemId> { 281) -> Vec<AssocItemId> {
275 let mut expander = Expander::new(db, impl_def.file_id, module_id);
276 let mut res = Vec::new(); 282 let mut res = Vec::new();
277 283
278 // We set a limit to protect against infinite recursion 284 // We set a limit to protect against infinite recursion
279 let limit = 100; 285 let limit = 100;
280 286
281 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 287 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
282 res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit)) 288 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit))
283 } 289 }
284 290
285 res 291 res
@@ -300,6 +306,7 @@ fn collect_impl_items_in_macro(
300 let items: InFile<ast::MacroItems> = expander.to_source(items); 306 let items: InFile<ast::MacroItems> = expander.to_source(items);
301 let mut res = collect_impl_items( 307 let mut res = collect_impl_items(
302 db, 308 db,
309 expander,
303 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 310 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
304 items.file_id, 311 items.file_id,
305 id, 312 id,
@@ -319,32 +326,26 @@ fn collect_impl_items_in_macro(
319 326
320fn collect_impl_items( 327fn collect_impl_items(
321 db: &dyn DefDatabase, 328 db: &dyn DefDatabase,
329 expander: &mut Expander,
322 impl_items: impl Iterator<Item = ImplItem>, 330 impl_items: impl Iterator<Item = ImplItem>,
323 file_id: crate::HirFileId, 331 file_id: crate::HirFileId,
324 id: ImplId, 332 id: ImplId,
325) -> Vec<AssocItemId> { 333) -> Vec<AssocItemId> {
326 let items = db.ast_id_map(file_id); 334 let items = db.ast_id_map(file_id);
327 let crate_graph = db.crate_graph();
328 let module_id = id.lookup(db).container.module(db);
329 335
330 impl_items 336 impl_items
331 .filter_map(|item_node| match item_node { 337 .filter_map(|item_node| match item_node {
332 ast::ImplItem::FnDef(it) => { 338 ast::ImplItem::FnDef(it) => {
339 let attrs = expander.parse_attrs(&it);
340 if !expander.is_cfg_enabled(&attrs) {
341 return None;
342 }
333 let def = FunctionLoc { 343 let def = FunctionLoc {
334 container: AssocContainerId::ImplId(id), 344 container: AssocContainerId::ImplId(id),
335 ast_id: AstId::new(file_id, items.ast_id(&it)), 345 ast_id: AstId::new(file_id, items.ast_id(&it)),
336 } 346 }
337 .intern(db); 347 .intern(db);
338 348 Some(def.into())
339 if !db
340 .function_data(def)
341 .attrs
342 .is_cfg_enabled(&crate_graph[module_id.krate].cfg_options)
343 {
344 None
345 } else {
346 Some(def.into())
347 }
348 } 349 }
349 ast::ImplItem::ConstDef(it) => { 350 ast::ImplItem::ConstDef(it) => {
350 let def = ConstLoc { 351 let def = ConstLoc {
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
index 095498429..cfa0f2f76 100644
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ b/crates/ra_hir_def/src/diagnostics.rs
@@ -20,7 +20,7 @@ impl Diagnostic for UnresolvedModule {
20 "unresolved module".to_string() 20 "unresolved module".to_string()
21 } 21 }
22 fn source(&self) -> InFile<SyntaxNodePtr> { 22 fn source(&self) -> InFile<SyntaxNodePtr> {
23 InFile { file_id: self.file, value: self.decl.into() } 23 InFile { file_id: self.file, value: self.decl.clone().into() }
24 } 24 }
25 fn as_any(&self) -> &(dyn Any + Send + 'static) { 25 fn as_any(&self) -> &(dyn Any + Send + 'static) {
26 self 26 self
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index 197bbe9bd..e11bdf3ec 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -376,35 +376,14 @@ pub enum Pat {
376 Wild, 376 Wild,
377 Tuple(Vec<PatId>), 377 Tuple(Vec<PatId>),
378 Or(Vec<PatId>), 378 Or(Vec<PatId>),
379 Record { 379 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool },
380 path: Option<Path>, 380 Range { start: ExprId, end: ExprId },
381 args: Vec<RecordFieldPat>, 381 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> },
382 // FIXME: 'ellipsis' option
383 },
384 Range {
385 start: ExprId,
386 end: ExprId,
387 },
388 Slice {
389 prefix: Vec<PatId>,
390 slice: Option<PatId>,
391 suffix: Vec<PatId>,
392 },
393 Path(Path), 382 Path(Path),
394 Lit(ExprId), 383 Lit(ExprId),
395 Bind { 384 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
396 mode: BindingAnnotation, 385 TupleStruct { path: Option<Path>, args: Vec<PatId> },
397 name: Name, 386 Ref { pat: PatId, mutability: Mutability },
398 subpat: Option<PatId>,
399 },
400 TupleStruct {
401 path: Option<Path>,
402 args: Vec<PatId>,
403 },
404 Ref {
405 pat: PatId,
406 mutability: Mutability,
407 },
408} 387}
409 388
410impl Pat { 389impl Pat {
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index 01b367278..d96ac8c0a 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -4,6 +4,7 @@
4//! features, such as Fn family of traits. 4//! features, such as Fn family of traits.
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use ra_prof::profile;
7use ra_syntax::SmolStr; 8use ra_syntax::SmolStr;
8use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
9 10
@@ -78,6 +79,8 @@ impl LangItems {
78 79
79 /// Salsa query. This will look for lang items in a specific crate. 80 /// Salsa query. This will look for lang items in a specific crate.
80 pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> { 81 pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> {
82 let _p = profile("crate_lang_items_query");
83
81 let mut lang_items = LangItems::default(); 84 let mut lang_items = LangItems::default();
82 85
83 let crate_def_map = db.crate_def_map(krate); 86 let crate_def_map = db.crate_def_map(krate);
@@ -95,6 +98,7 @@ impl LangItems {
95 db: &dyn DefDatabase, 98 db: &dyn DefDatabase,
96 module: ModuleId, 99 module: ModuleId,
97 ) -> Option<Arc<LangItems>> { 100 ) -> Option<Arc<LangItems>> {
101 let _p = profile("module_lang_items_query");
98 let mut lang_items = LangItems::default(); 102 let mut lang_items = LangItems::default();
99 lang_items.collect_lang_items(db, module); 103 lang_items.collect_lang_items(db, module);
100 if lang_items.items.is_empty() { 104 if lang_items.items.is_empty() {
@@ -111,6 +115,7 @@ impl LangItems {
111 start_crate: CrateId, 115 start_crate: CrateId,
112 item: SmolStr, 116 item: SmolStr,
113 ) -> Option<LangItemTarget> { 117 ) -> Option<LangItemTarget> {
118 let _p = profile("lang_item_query");
114 let lang_items = db.crate_lang_items(start_crate); 119 let lang_items = db.crate_lang_items(start_crate);
115 let start_crate_target = lang_items.items.get(&item); 120 let start_crate_target = lang_items.items.get(&item);
116 if let Some(target) = start_crate_target { 121 if let Some(target) = start_crate_target {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 8fe3f8617..98c74fe25 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -462,6 +462,14 @@ impl DefCollector<'_> {
462 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { 462 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
463 tested_by!(glob_enum); 463 tested_by!(glob_enum);
464 // glob import from enum => just import all the variants 464 // glob import from enum => just import all the variants
465
466 // XXX: urgh, so this works by accident! Here, we look at
467 // the enum data, and, in theory, this might require us to
468 // look back at the crate_def_map, creating a cycle. For
469 // example, `enum E { crate::some_macro!(); }`. Luckely, the
470 // only kind of macro that is allowed inside enum is a
471 // `cfg_macro`, and we don't need to run name resolution for
472 // it, but this is sheer luck!
465 let enum_data = self.db.enum_data(e); 473 let enum_data = self.db.enum_data(e);
466 let resolutions = enum_data 474 let resolutions = enum_data
467 .variants 475 .variants
@@ -977,11 +985,7 @@ impl ModCollector<'_, '_> {
977 } 985 }
978 986
979 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 987 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
980 // FIXME: handle cfg_attr :-) 988 attrs.is_cfg_enabled(self.def_collector.cfg_options)
981 attrs
982 .by_key("cfg")
983 .tt_values()
984 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
985 } 989 }
986} 990}
987 991
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index e72ba52cf..afd538e4a 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -287,7 +287,7 @@ impl RawItemsCollector {
287 let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene); 287 let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene);
288 288
289 let ast_id = self.source_ast_id_map.ast_id(&module); 289 let ast_id = self.source_ast_id_map.ast_id(&module);
290 if module.semi_token().is_some() { 290 if module.semicolon_token().is_some() {
291 let item = 291 let item =
292 self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id }); 292 self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id });
293 self.push_item(current_module, attrs, RawItemKind::Module(item)); 293 self.push_item(current_module, attrs, RawItemKind::Module(item));
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs
index 496fc6b08..87165ac33 100644
--- a/crates/ra_hir_def/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs
@@ -32,6 +32,9 @@ fn typing_inside_a_function_should_not_invalidate_def_map() {
32 32
33 use crate::foo::bar::Baz; 33 use crate::foo::bar::Baz;
34 34
35 enum E { A, B }
36 use E::*;
37
35 fn foo() -> i32 { 38 fn foo() -> i32 {
36 1 + 1 39 1 + 1
37 } 40 }
@@ -46,6 +49,9 @@ fn typing_inside_a_function_should_not_invalidate_def_map() {
46 49
47 use crate::foo::bar::Baz; 50 use crate::foo::bar::Baz;
48 51
52 enum E { A, B }
53 use E::*;
54
49 fn foo() -> i32 { 92 } 55 fn foo() -> i32 { 92 }
50 ", 56 ",
51 ); 57 );
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 904080341..91c7b3e09 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -134,11 +134,6 @@ impl Path {
134 lower::lower_path(path, hygiene) 134 lower::lower_path(path, hygiene)
135 } 135 }
136 136
137 /// Converts an `ast::NameRef` into a single-identifier `Path`.
138 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
139 Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
140 }
141
142 /// Converts a known mod path to `Path`. 137 /// Converts a known mod path to `Path`.
143 pub(crate) fn from_known_path( 138 pub(crate) fn from_known_path(
144 path: ModPath, 139 path: ModPath,