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/Cargo.toml2
-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.rs66
-rw-r--r--crates/ra_hir_def/src/body/lower.rs80
-rw-r--r--crates/ra_hir_def/src/data.rs63
-rw-r--r--crates/ra_hir_def/src/expr.rs6
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs14
-rw-r--r--crates/ra_hir_def/src/nameres/tests/incremental.rs6
-rw-r--r--crates/ra_hir_def/src/path.rs26
-rw-r--r--crates/ra_hir_def/src/path/lower.rs21
-rw-r--r--crates/ra_hir_def/src/type_ref.rs12
12 files changed, 202 insertions, 115 deletions
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml
index 56e791e3e..b85358308 100644
--- a/crates/ra_hir_def/Cargo.toml
+++ b/crates/ra_hir_def/Cargo.toml
@@ -28,4 +28,4 @@ ra_cfg = { path = "../ra_cfg" }
28tt = { path = "../ra_tt", package = "ra_tt" } 28tt = { path = "../ra_tt", package = "ra_tt" }
29 29
30[dev-dependencies] 30[dev-dependencies]
31insta = "0.15.0" 31insta = "0.16.0"
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 e09996c6f..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>>;
@@ -240,7 +285,7 @@ impl BodySourceMap {
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,11 +294,6 @@ 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].clone() 298 self.pat_map_back[pat].clone()
259 } 299 }
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 9d6ee095e..79abe55ce 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,14 @@ 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};
36use ast::AstChildren;
37
40pub(super) fn lower( 38pub(super) fn lower(
41 db: &dyn DefDatabase, 39 db: &dyn DefDatabase,
42 def: DefWithBodyId, 40 def: DefWithBodyId,
@@ -104,7 +102,6 @@ impl ExprCollector<'_> {
104 } 102 }
105 103
106 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 104 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); 105 let src = self.expander.to_source(ptr);
109 let id = self.make_expr(expr, Ok(src.clone())); 106 let id = self.make_expr(expr, Ok(src.clone()));
110 self.source_map.expr_map.insert(src, id); 107 self.source_map.expr_map.insert(src, id);
@@ -115,13 +112,6 @@ impl ExprCollector<'_> {
115 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { 112 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
116 self.make_expr(expr, Err(SyntheticSyntax)) 113 self.make_expr(expr, Err(SyntheticSyntax))
117 } 114 }
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.clone()));
122 self.source_map.expr_map.insert(src, id);
123 id
124 }
125 fn empty_block(&mut self) -> ExprId { 115 fn empty_block(&mut self) -> ExprId {
126 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) 116 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None })
127 } 117 }
@@ -291,7 +281,7 @@ impl ExprCollector<'_> {
291 ast::Expr::ParenExpr(e) => { 281 ast::Expr::ParenExpr(e) => {
292 let inner = self.collect_expr_opt(e.expr()); 282 let inner = self.collect_expr_opt(e.expr());
293 // make the paren expr point to the inner expression as well 283 // make the paren expr point to the inner expression as well
294 let src = self.expander.to_source(Either::Left(syntax_ptr)); 284 let src = self.expander.to_source(syntax_ptr);
295 self.source_map.expr_map.insert(src, inner); 285 self.source_map.expr_map.insert(src, inner);
296 inner 286 inner
297 } 287 }
@@ -300,7 +290,6 @@ impl ExprCollector<'_> {
300 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 290 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
301 } 291 }
302 ast::Expr::RecordLit(e) => { 292 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)); 293 let path = e.path().and_then(|path| self.expander.parse_path(path));
305 let mut field_ptrs = Vec::new(); 294 let mut field_ptrs = Vec::new();
306 let record_lit = if let Some(nfl) = e.record_field_list() { 295 let record_lit = if let Some(nfl) = e.record_field_list() {
@@ -308,31 +297,17 @@ impl ExprCollector<'_> {
308 .fields() 297 .fields()
309 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 298 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
310 .filter_map(|field| { 299 .filter_map(|field| {
311 let module_id = ContainerId::DefWithBodyId(self.def).module(self.db); 300 let attrs = self.expander.parse_attrs(&field);
312 let attrs = Attrs::new( 301 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; 302 return None;
319 } 303 }
304 let name = field.field_name()?.as_name();
320 305
321 Some(RecordLitField { 306 Some(RecordLitField {
322 name: field 307 name,
323 .name_ref() 308 expr: match field.expr() {
324 .map(|nr| nr.as_name()) 309 Some(e) => self.collect_expr(e),
325 .unwrap_or_else(Name::missing), 310 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 }, 311 },
337 }) 312 })
338 }) 313 })
@@ -624,8 +599,8 @@ impl ExprCollector<'_> {
624 } 599 }
625 ast::Pat::TupleStructPat(p) => { 600 ast::Pat::TupleStructPat(p) => {
626 let path = p.path().and_then(|path| self.expander.parse_path(path)); 601 let path = p.path().and_then(|path| self.expander.parse_path(path));
627 let args = p.args().map(|p| self.collect_pat(p)).collect(); 602 let (args, ellipsis) = self.collect_tuple_pat(p.args());
628 Pat::TupleStruct { path, args } 603 Pat::TupleStruct { path, args, ellipsis }
629 } 604 }
630 ast::Pat::RefPat(p) => { 605 ast::Pat::RefPat(p) => {
631 let pat = self.collect_pat_opt(p.pat()); 606 let pat = self.collect_pat_opt(p.pat());
@@ -642,10 +617,10 @@ impl ExprCollector<'_> {
642 } 617 }
643 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), 618 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()),
644 ast::Pat::TuplePat(p) => { 619 ast::Pat::TuplePat(p) => {
645 let args = p.args().map(|p| self.collect_pat(p)).collect(); 620 let (args, ellipsis) = self.collect_tuple_pat(p.args());
646 Pat::Tuple(args) 621 Pat::Tuple { args, ellipsis }
647 } 622 }
648 ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild, 623 ast::Pat::PlaceholderPat(_) => Pat::Wild,
649 ast::Pat::RecordPat(p) => { 624 ast::Pat::RecordPat(p) => {
650 let path = p.path().and_then(|path| self.expander.parse_path(path)); 625 let path = p.path().and_then(|path| self.expander.parse_path(path));
651 let record_field_pat_list = 626 let record_field_pat_list =
@@ -663,7 +638,7 @@ impl ExprCollector<'_> {
663 let iter = record_field_pat_list.record_field_pats().filter_map(|f| { 638 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
664 let ast_pat = f.pat()?; 639 let ast_pat = f.pat()?;
665 let pat = self.collect_pat(ast_pat); 640 let pat = self.collect_pat(ast_pat);
666 let name = f.name()?.as_name(); 641 let name = f.field_name()?.as_name();
667 Some(RecordFieldPat { name, pat }) 642 Some(RecordFieldPat { name, pat })
668 }); 643 });
669 fields.extend(iter); 644 fields.extend(iter);
@@ -691,7 +666,9 @@ impl ExprCollector<'_> {
691 Pat::Missing 666 Pat::Missing
692 } 667 }
693 } 668 }
694 669 ast::Pat::DotDotPat(_) => unreachable!(
670 "`DotDotPat` requires special handling and should not be mapped to a Pat."
671 ),
695 // FIXME: implement 672 // FIXME: implement
696 ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, 673 ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
697 }; 674 };
@@ -706,6 +683,19 @@ impl ExprCollector<'_> {
706 self.missing_pat() 683 self.missing_pat()
707 } 684 }
708 } 685 }
686
687 fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) {
688 // Find the location of the `..`, if there is one. Note that we do not
689 // consider the possiblity of there being multiple `..` here.
690 let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_)));
691 // We want to skip the `..` pattern here, since we account for it above.
692 let args = args
693 .filter(|p| !matches!(p, ast::Pat::DotDotPat(_)))
694 .map(|p| self.collect_pat(p))
695 .collect();
696
697 (args, ellipsis)
698 }
709} 699}
710 700
711impl From<ast::BinOp> for BinaryOp { 701impl From<ast::BinOp> for BinaryOp {
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index b8fbf0ed4..ccb682f9a 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -9,18 +9,19 @@ use hir_expand::{
9}; 9};
10use ra_prof::profile; 10use ra_prof::profile;
11use ra_syntax::ast::{ 11use ra_syntax::ast::{
12 self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, 12 self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner,
13 VisibilityOwner,
13}; 14};
14 15
15use crate::{ 16use crate::{
16 attr::Attrs, 17 attr::Attrs,
17 db::DefDatabase, 18 db::DefDatabase,
18 path::{path, GenericArgs, Path}, 19 path::{path, AssociatedTypeBinding, GenericArgs, Path},
19 src::HasSource, 20 src::HasSource,
20 type_ref::{Mutability, TypeBound, TypeRef}, 21 type_ref::{Mutability, TypeBound, TypeRef},
21 visibility::RawVisibility, 22 visibility::RawVisibility,
22 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, 23 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
23 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 24 ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
24}; 25};
25 26
26#[derive(Debug, Clone, PartialEq, Eq)] 27#[derive(Debug, Clone, PartialEq, Eq)]
@@ -95,7 +96,11 @@ fn desugar_future_path(orig: TypeRef) -> Path {
95 let path = path![std::future::Future]; 96 let path = path![std::future::Future];
96 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); 97 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect();
97 let mut last = GenericArgs::empty(); 98 let mut last = GenericArgs::empty();
98 last.bindings.push((name![Output], orig)); 99 last.bindings.push(AssociatedTypeBinding {
100 name: name![Output],
101 type_ref: Some(orig),
102 bounds: Vec::new(),
103 });
99 generic_args.push(Some(Arc::new(last))); 104 generic_args.push(Some(Arc::new(last)));
100 105
101 Path::from_known_path(path, generic_args) 106 Path::from_known_path(path, generic_args)
@@ -106,6 +111,7 @@ pub struct TypeAliasData {
106 pub name: Name, 111 pub name: Name,
107 pub type_ref: Option<TypeRef>, 112 pub type_ref: Option<TypeRef>,
108 pub visibility: RawVisibility, 113 pub visibility: RawVisibility,
114 pub bounds: Vec<TypeBound>,
109} 115}
110 116
111impl TypeAliasData { 117impl TypeAliasData {
@@ -118,9 +124,17 @@ impl TypeAliasData {
118 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); 124 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name());
119 let type_ref = node.value.type_ref().map(TypeRef::from_ast); 125 let type_ref = node.value.type_ref().map(TypeRef::from_ast);
120 let vis_default = RawVisibility::default_for_container(loc.container); 126 let vis_default = RawVisibility::default_for_container(loc.container);
121 let visibility = 127 let visibility = RawVisibility::from_ast_with_default(
122 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); 128 db,
123 Arc::new(TypeAliasData { name, type_ref, visibility }) 129 vis_default,
130 node.as_ref().map(|n| n.visibility()),
131 );
132 let bounds = if let Some(bound_list) = node.value.type_bound_list() {
133 bound_list.bounds().map(TypeBound::from_ast).collect()
134 } else {
135 Vec::new()
136 };
137 Arc::new(TypeAliasData { name, type_ref, visibility, bounds })
124 } 138 }
125} 139}
126 140
@@ -218,10 +232,17 @@ impl ImplData {
218 let mut items = Vec::new(); 232 let mut items = Vec::new();
219 233
220 if let Some(item_list) = src.value.item_list() { 234 if let Some(item_list) = src.value.item_list() {
221 items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); 235 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
236 items.extend(collect_impl_items(
237 db,
238 &mut expander,
239 item_list.impl_items(),
240 src.file_id,
241 id,
242 ));
222 items.extend(collect_impl_items_in_macros( 243 items.extend(collect_impl_items_in_macros(
223 db, 244 db,
224 module_id, 245 &mut expander,
225 &src.with_value(item_list), 246 &src.with_value(item_list),
226 id, 247 id,
227 )); 248 ));
@@ -268,18 +289,17 @@ impl ConstData {
268 289
269fn collect_impl_items_in_macros( 290fn collect_impl_items_in_macros(
270 db: &dyn DefDatabase, 291 db: &dyn DefDatabase,
271 module_id: ModuleId, 292 expander: &mut Expander,
272 impl_def: &InFile<ast::ItemList>, 293 impl_def: &InFile<ast::ItemList>,
273 id: ImplId, 294 id: ImplId,
274) -> Vec<AssocItemId> { 295) -> Vec<AssocItemId> {
275 let mut expander = Expander::new(db, impl_def.file_id, module_id);
276 let mut res = Vec::new(); 296 let mut res = Vec::new();
277 297
278 // We set a limit to protect against infinite recursion 298 // We set a limit to protect against infinite recursion
279 let limit = 100; 299 let limit = 100;
280 300
281 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 301 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)) 302 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit))
283 } 303 }
284 304
285 res 305 res
@@ -300,6 +320,7 @@ fn collect_impl_items_in_macro(
300 let items: InFile<ast::MacroItems> = expander.to_source(items); 320 let items: InFile<ast::MacroItems> = expander.to_source(items);
301 let mut res = collect_impl_items( 321 let mut res = collect_impl_items(
302 db, 322 db,
323 expander,
303 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 324 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
304 items.file_id, 325 items.file_id,
305 id, 326 id,
@@ -319,32 +340,26 @@ fn collect_impl_items_in_macro(
319 340
320fn collect_impl_items( 341fn collect_impl_items(
321 db: &dyn DefDatabase, 342 db: &dyn DefDatabase,
343 expander: &mut Expander,
322 impl_items: impl Iterator<Item = ImplItem>, 344 impl_items: impl Iterator<Item = ImplItem>,
323 file_id: crate::HirFileId, 345 file_id: crate::HirFileId,
324 id: ImplId, 346 id: ImplId,
325) -> Vec<AssocItemId> { 347) -> Vec<AssocItemId> {
326 let items = db.ast_id_map(file_id); 348 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 349
330 impl_items 350 impl_items
331 .filter_map(|item_node| match item_node { 351 .filter_map(|item_node| match item_node {
332 ast::ImplItem::FnDef(it) => { 352 ast::ImplItem::FnDef(it) => {
353 let attrs = expander.parse_attrs(&it);
354 if !expander.is_cfg_enabled(&attrs) {
355 return None;
356 }
333 let def = FunctionLoc { 357 let def = FunctionLoc {
334 container: AssocContainerId::ImplId(id), 358 container: AssocContainerId::ImplId(id),
335 ast_id: AstId::new(file_id, items.ast_id(&it)), 359 ast_id: AstId::new(file_id, items.ast_id(&it)),
336 } 360 }
337 .intern(db); 361 .intern(db);
338 362 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 } 363 }
349 ast::ImplItem::ConstDef(it) => { 364 ast::ImplItem::ConstDef(it) => {
350 let def = ConstLoc { 365 let def = ConstLoc {
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index e11bdf3ec..a0cdad529 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -374,7 +374,7 @@ pub struct RecordFieldPat {
374pub enum Pat { 374pub enum Pat {
375 Missing, 375 Missing,
376 Wild, 376 Wild,
377 Tuple(Vec<PatId>), 377 Tuple { args: Vec<PatId>, ellipsis: Option<usize> },
378 Or(Vec<PatId>), 378 Or(Vec<PatId>),
379 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, 379 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool },
380 Range { start: ExprId, end: ExprId }, 380 Range { start: ExprId, end: ExprId },
@@ -382,7 +382,7 @@ pub enum Pat {
382 Path(Path), 382 Path(Path),
383 Lit(ExprId), 383 Lit(ExprId),
384 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, 384 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
385 TupleStruct { path: Option<Path>, args: Vec<PatId> }, 385 TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> },
386 Ref { pat: PatId, mutability: Mutability }, 386 Ref { pat: PatId, mutability: Mutability },
387} 387}
388 388
@@ -393,7 +393,7 @@ impl Pat {
393 Pat::Bind { subpat, .. } => { 393 Pat::Bind { subpat, .. } => {
394 subpat.iter().copied().for_each(f); 394 subpat.iter().copied().for_each(f);
395 } 395 }
396 Pat::Or(args) | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { 396 Pat::Or(args) | Pat::Tuple { args, .. } | Pat::TupleStruct { args, .. } => {
397 args.iter().copied().for_each(f); 397 args.iter().copied().for_each(f);
398 } 398 }
399 Pat::Ref { pat, .. } => f(*pat), 399 Pat::Ref { pat, .. } => f(*pat),
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/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..162b3c8c7 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -14,7 +14,10 @@ use hir_expand::{
14use ra_db::CrateId; 14use ra_db::CrateId;
15use ra_syntax::ast; 15use ra_syntax::ast;
16 16
17use crate::{type_ref::TypeRef, InFile}; 17use crate::{
18 type_ref::{TypeBound, TypeRef},
19 InFile,
20};
18 21
19#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 22#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub struct ModPath { 23pub struct ModPath {
@@ -111,7 +114,21 @@ pub struct GenericArgs {
111 /// is left out. 114 /// is left out.
112 pub has_self_type: bool, 115 pub has_self_type: bool,
113 /// Associated type bindings like in `Iterator<Item = T>`. 116 /// Associated type bindings like in `Iterator<Item = T>`.
114 pub bindings: Vec<(Name, TypeRef)>, 117 pub bindings: Vec<AssociatedTypeBinding>,
118}
119
120/// An associated type binding like in `Iterator<Item = T>`.
121#[derive(Debug, Clone, PartialEq, Eq, Hash)]
122pub struct AssociatedTypeBinding {
123 /// The name of the associated type.
124 pub name: Name,
125 /// The type bound to this associated type (in `Item = T`, this would be the
126 /// `T`). This can be `None` if there are bounds instead.
127 pub type_ref: Option<TypeRef>,
128 /// Bounds for the associated type, like in `Iterator<Item:
129 /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds`
130 /// feature.)
131 pub bounds: Vec<TypeBound>,
115} 132}
116 133
117/// A single generic argument. 134/// A single generic argument.
@@ -134,11 +151,6 @@ impl Path {
134 lower::lower_path(path, hygiene) 151 lower::lower_path(path, hygiene)
135 } 152 }
136 153
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`. 154 /// Converts a known mod path to `Path`.
143 pub(crate) fn from_known_path( 155 pub(crate) fn from_known_path(
144 path: ModPath, 156 path: ModPath,
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index 0f806d6fb..9ec2e0dcd 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -9,11 +9,12 @@ use hir_expand::{
9 hygiene::Hygiene, 9 hygiene::Hygiene,
10 name::{name, AsName}, 10 name::{name, AsName},
11}; 11};
12use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner}; 12use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner};
13 13
14use super::AssociatedTypeBinding;
14use crate::{ 15use crate::{
15 path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, 16 path::{GenericArg, GenericArgs, ModPath, Path, PathKind},
16 type_ref::TypeRef, 17 type_ref::{TypeBound, TypeRef},
17}; 18};
18 19
19pub(super) use lower_use::lower_use_tree; 20pub(super) use lower_use::lower_use_tree;
@@ -136,10 +137,16 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
136 // lifetimes ignored for now 137 // lifetimes ignored for now
137 let mut bindings = Vec::new(); 138 let mut bindings = Vec::new();
138 for assoc_type_arg in node.assoc_type_args() { 139 for assoc_type_arg in node.assoc_type_args() {
140 let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg;
139 if let Some(name_ref) = assoc_type_arg.name_ref() { 141 if let Some(name_ref) = assoc_type_arg.name_ref() {
140 let name = name_ref.as_name(); 142 let name = name_ref.as_name();
141 let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref()); 143 let type_ref = assoc_type_arg.type_ref().map(TypeRef::from_ast);
142 bindings.push((name, type_ref)); 144 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
145 l.bounds().map(TypeBound::from_ast).collect()
146 } else {
147 Vec::new()
148 };
149 bindings.push(AssociatedTypeBinding { name, type_ref, bounds });
143 } 150 }
144 } 151 }
145 if args.is_empty() && bindings.is_empty() { 152 if args.is_empty() && bindings.is_empty() {
@@ -168,7 +175,11 @@ fn lower_generic_args_from_fn_path(
168 } 175 }
169 if let Some(ret_type) = ret_type { 176 if let Some(ret_type) = ret_type {
170 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); 177 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
171 bindings.push((name![Output], type_ref)) 178 bindings.push(AssociatedTypeBinding {
179 name: name![Output],
180 type_ref: Some(type_ref),
181 bounds: Vec::new(),
182 });
172 } 183 }
173 if args.is_empty() && bindings.is_empty() { 184 if args.is_empty() && bindings.is_empty() {
174 None 185 None
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index ea29c4176..f308c6bdf 100644
--- a/crates/ra_hir_def/src/type_ref.rs
+++ b/crates/ra_hir_def/src/type_ref.rs
@@ -163,8 +163,16 @@ impl TypeRef {
163 let crate::path::GenericArg::Type(type_ref) = arg; 163 let crate::path::GenericArg::Type(type_ref) = arg;
164 go(type_ref, f); 164 go(type_ref, f);
165 } 165 }
166 for (_, type_ref) in &args_and_bindings.bindings { 166 for binding in &args_and_bindings.bindings {
167 go(type_ref, f); 167 if let Some(type_ref) = &binding.type_ref {
168 go(type_ref, f);
169 }
170 for bound in &binding.bounds {
171 match bound {
172 TypeBound::Path(path) => go_path(path, f),
173 TypeBound::Error => (),
174 }
175 }
168 } 176 }
169 } 177 }
170 } 178 }