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.rs15
-rw-r--r--crates/ra_hir_def/src/attr.rs1
-rw-r--r--crates/ra_hir_def/src/body.rs11
-rw-r--r--crates/ra_hir_def/src/body/lower.rs63
-rw-r--r--crates/ra_hir_def/src/body/scope.rs4
-rw-r--r--crates/ra_hir_def/src/data.rs194
-rw-r--r--crates/ra_hir_def/src/db.rs22
-rw-r--r--crates/ra_hir_def/src/expr.rs4
-rw-r--r--crates/ra_hir_def/src/find_path.rs105
-rw-r--r--crates/ra_hir_def/src/item_scope.rs11
-rw-r--r--crates/ra_hir_def/src/lib.rs2
-rw-r--r--crates/ra_hir_def/src/marks.rs17
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs29
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs8
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs51
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs10
-rw-r--r--crates/ra_hir_def/src/nameres/tests/globs.rs7
-rw-r--r--crates/ra_hir_def/src/nameres/tests/macros.rs70
-rw-r--r--crates/ra_hir_def/src/nameres/tests/mod_resolution.rs2
-rw-r--r--crates/ra_hir_def/src/path/lower.rs15
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs4
-rw-r--r--crates/ra_hir_def/src/resolver.rs18
22 files changed, 391 insertions, 272 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 8eef51828..2bc34d449 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -117,7 +117,14 @@ fn lower_enum(
117 ast: &InFile<ast::EnumDef>, 117 ast: &InFile<ast::EnumDef>,
118 module_id: ModuleId, 118 module_id: ModuleId,
119) { 119) {
120 for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { 120 let expander = CfgExpander::new(db, ast.file_id, module_id.krate);
121 let variants = ast
122 .value
123 .variant_list()
124 .into_iter()
125 .flat_map(|it| it.variants())
126 .filter(|var| expander.is_cfg_enabled(var));
127 for var in variants {
121 trace.alloc( 128 trace.alloc(
122 || var.clone(), 129 || var.clone(),
123 || EnumVariantData { 130 || EnumVariantData {
@@ -209,8 +216,7 @@ fn lower_struct(
209 match &ast.value { 216 match &ast.value {
210 ast::StructKind::Tuple(fl) => { 217 ast::StructKind::Tuple(fl) => {
211 for (i, fd) in fl.fields().enumerate() { 218 for (i, fd) in fl.fields().enumerate() {
212 let attrs = expander.parse_attrs(&fd); 219 if !expander.is_cfg_enabled(&fd) {
213 if !expander.is_cfg_enabled(&attrs) {
214 continue; 220 continue;
215 } 221 }
216 222
@@ -227,8 +233,7 @@ fn lower_struct(
227 } 233 }
228 ast::StructKind::Record(fl) => { 234 ast::StructKind::Record(fl) => {
229 for fd in fl.fields() { 235 for fd in fl.fields() {
230 let attrs = expander.parse_attrs(&fd); 236 if !expander.is_cfg_enabled(&fd) {
231 if !expander.is_cfg_enabled(&attrs) {
232 continue; 237 continue;
233 } 238 }
234 239
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 5a86af8ba..576cd0c65 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -140,6 +140,7 @@ impl Attr {
140 } 140 }
141} 141}
142 142
143#[derive(Debug, Clone, Copy)]
143pub struct AttrQuery<'a> { 144pub struct AttrQuery<'a> {
144 attrs: &'a Attrs, 145 attrs: &'a Attrs,
145 key: &'static str, 146 key: &'static str,
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 4edaad960..f5a7305dc 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -60,7 +60,8 @@ impl CfgExpander {
60 Attrs::new(owner, &self.hygiene) 60 Attrs::new(owner, &self.hygiene)
61 } 61 }
62 62
63 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 63 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
64 let attrs = self.parse_attrs(owner);
64 attrs.is_cfg_enabled(&self.cfg_options) 65 attrs.is_cfg_enabled(&self.cfg_options)
65 } 66 }
66} 67}
@@ -141,12 +142,8 @@ impl Expander {
141 InFile { file_id: self.current_file_id, value } 142 InFile { file_id: self.current_file_id, value }
142 } 143 }
143 144
144 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { 145 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
145 self.cfg_expander.parse_attrs(owner) 146 self.cfg_expander.is_cfg_enabled(owner)
146 }
147
148 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
149 self.cfg_expander.is_cfg_enabled(attrs)
150 } 147 }
151 148
152 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 149 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index e9dd65b0a..e08d62dd6 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -15,7 +15,7 @@ use ra_syntax::{
15 }, 15 },
16 AstNode, AstPtr, 16 AstNode, AstPtr,
17}; 17};
18use test_utils::tested_by; 18use test_utils::mark;
19 19
20use crate::{ 20use crate::{
21 adt::StructKind, 21 adt::StructKind,
@@ -60,13 +60,10 @@ pub(super) fn lower(
60 params: Option<ast::ParamList>, 60 params: Option<ast::ParamList>,
61 body: Option<ast::Expr>, 61 body: Option<ast::Expr>,
62) -> (Body, BodySourceMap) { 62) -> (Body, BodySourceMap) {
63 let ctx = LowerCtx::new(db, expander.current_file_id.clone());
64
65 ExprCollector { 63 ExprCollector {
66 db, 64 db,
67 def, 65 def,
68 expander, 66 expander,
69 ctx,
70 source_map: BodySourceMap::default(), 67 source_map: BodySourceMap::default(),
71 body: Body { 68 body: Body {
72 exprs: Arena::default(), 69 exprs: Arena::default(),
@@ -83,7 +80,6 @@ struct ExprCollector<'a> {
83 db: &'a dyn DefDatabase, 80 db: &'a dyn DefDatabase,
84 def: DefWithBodyId, 81 def: DefWithBodyId,
85 expander: Expander, 82 expander: Expander,
86 ctx: LowerCtx,
87 body: Body, 83 body: Body,
88 source_map: BodySourceMap, 84 source_map: BodySourceMap,
89} 85}
@@ -122,6 +118,10 @@ impl ExprCollector<'_> {
122 (self.body, self.source_map) 118 (self.body, self.source_map)
123 } 119 }
124 120
121 fn ctx(&self) -> LowerCtx {
122 LowerCtx::new(self.db, self.expander.current_file_id)
123 }
124
125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
126 let src = self.expander.to_source(ptr); 126 let src = self.expander.to_source(ptr);
127 let id = self.make_expr(expr, Ok(src.clone())); 127 let id = self.make_expr(expr, Ok(src.clone()));
@@ -162,8 +162,7 @@ impl ExprCollector<'_> {
162 162
163 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 163 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
164 let syntax_ptr = AstPtr::new(&expr); 164 let syntax_ptr = AstPtr::new(&expr);
165 let attrs = self.expander.parse_attrs(&expr); 165 if !self.expander.is_cfg_enabled(&expr) {
166 if !self.expander.is_cfg_enabled(&attrs) {
167 return self.missing_expr(); 166 return self.missing_expr();
168 } 167 }
169 match expr { 168 match expr {
@@ -203,6 +202,16 @@ impl ExprCollector<'_> {
203 202
204 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) 203 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
205 } 204 }
205 ast::Expr::EffectExpr(e) => match e.effect() {
206 ast::Effect::Try(_) => {
207 let body = self.collect_block_opt(e.block_expr());
208 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
209 }
210 // FIXME: we need to record these effects somewhere...
211 ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => {
212 self.collect_block_opt(e.block_expr())
213 }
214 },
206 ast::Expr::BlockExpr(e) => self.collect_block(e), 215 ast::Expr::BlockExpr(e) => self.collect_block(e),
207 ast::Expr::LoopExpr(e) => { 216 ast::Expr::LoopExpr(e) => {
208 let body = self.collect_block_opt(e.loop_body()); 217 let body = self.collect_block_opt(e.loop_body());
@@ -217,7 +226,7 @@ impl ExprCollector<'_> {
217 None => self.collect_expr_opt(condition.expr()), 226 None => self.collect_expr_opt(condition.expr()),
218 // if let -- desugar to match 227 // if let -- desugar to match
219 Some(pat) => { 228 Some(pat) => {
220 tested_by!(infer_resolve_while_let); 229 mark::hit!(infer_resolve_while_let);
221 let pat = self.collect_pat(pat); 230 let pat = self.collect_pat(pat);
222 let match_expr = self.collect_expr_opt(condition.expr()); 231 let match_expr = self.collect_expr_opt(condition.expr());
223 let placeholder_pat = self.missing_pat(); 232 let placeholder_pat = self.missing_pat();
@@ -259,7 +268,7 @@ impl ExprCollector<'_> {
259 }; 268 };
260 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 269 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
261 let generic_args = 270 let generic_args =
262 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it)); 271 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
263 self.alloc_expr( 272 self.alloc_expr(
264 Expr::MethodCall { receiver, method_name, args, generic_args }, 273 Expr::MethodCall { receiver, method_name, args, generic_args },
265 syntax_ptr, 274 syntax_ptr,
@@ -319,8 +328,7 @@ impl ExprCollector<'_> {
319 .fields() 328 .fields()
320 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 329 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
321 .filter_map(|field| { 330 .filter_map(|field| {
322 let attrs = self.expander.parse_attrs(&field); 331 if !self.expander.is_cfg_enabled(&field) {
323 if !self.expander.is_cfg_enabled(&attrs) {
324 return None; 332 return None;
325 } 333 }
326 let name = field.field_name()?.as_name(); 334 let name = field.field_name()?.as_name();
@@ -365,7 +373,7 @@ impl ExprCollector<'_> {
365 } 373 }
366 ast::Expr::CastExpr(e) => { 374 ast::Expr::CastExpr(e) => {
367 let expr = self.collect_expr_opt(e.expr()); 375 let expr = self.collect_expr_opt(e.expr());
368 let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref()); 376 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
369 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 377 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
370 } 378 }
371 ast::Expr::RefExpr(e) => { 379 ast::Expr::RefExpr(e) => {
@@ -388,7 +396,7 @@ impl ExprCollector<'_> {
388 for param in pl.params() { 396 for param in pl.params() {
389 let pat = self.collect_pat_opt(param.pat()); 397 let pat = self.collect_pat_opt(param.pat());
390 let type_ref = 398 let type_ref =
391 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); 399 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
392 args.push(pat); 400 args.push(pat);
393 arg_types.push(type_ref); 401 arg_types.push(type_ref);
394 } 402 }
@@ -396,7 +404,7 @@ impl ExprCollector<'_> {
396 let ret_type = e 404 let ret_type = e
397 .ret_type() 405 .ret_type()
398 .and_then(|r| r.type_ref()) 406 .and_then(|r| r.type_ref())
399 .map(|it| TypeRef::from_ast(&self.ctx, it)); 407 .map(|it| TypeRef::from_ast(&self.ctx(), it));
400 let body = self.collect_expr_opt(e.body()); 408 let body = self.collect_expr_opt(e.body());
401 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 409 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
402 } 410 }
@@ -456,6 +464,7 @@ impl ExprCollector<'_> {
456 krate: Some(self.expander.module.krate), 464 krate: Some(self.expander.module.krate),
457 ast_id: Some(self.expander.ast_id(&e)), 465 ast_id: Some(self.expander.ast_id(&e)),
458 kind: MacroDefKind::Declarative, 466 kind: MacroDefKind::Declarative,
467 local_inner: false,
459 }; 468 };
460 self.body.item_scope.define_legacy_macro(name, mac); 469 self.body.item_scope.define_legacy_macro(name, mac);
461 470
@@ -490,19 +499,16 @@ impl ExprCollector<'_> {
490 } 499 }
491 } 500 }
492 501
493 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { 502 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
494 let syntax_node_ptr = AstPtr::new(&expr.clone().into()); 503 let syntax_node_ptr = AstPtr::new(&block.clone().into());
495 let block = match expr.block() {
496 Some(block) => block,
497 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
498 };
499 self.collect_block_items(&block); 504 self.collect_block_items(&block);
500 let statements = block 505 let statements = block
501 .statements() 506 .statements()
502 .map(|s| match s { 507 .map(|s| match s {
503 ast::Stmt::LetStmt(stmt) => { 508 ast::Stmt::LetStmt(stmt) => {
504 let pat = self.collect_pat_opt(stmt.pat()); 509 let pat = self.collect_pat_opt(stmt.pat());
505 let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); 510 let type_ref =
511 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
506 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 512 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
507 Statement::Let { pat, type_ref, initializer } 513 Statement::Let { pat, type_ref, initializer }
508 } 514 }
@@ -513,7 +519,7 @@ impl ExprCollector<'_> {
513 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 519 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
514 } 520 }
515 521
516 fn collect_block_items(&mut self, block: &ast::Block) { 522 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
517 let container = ContainerId::DefWithBodyId(self.def); 523 let container = ContainerId::DefWithBodyId(self.def);
518 for item in block.items() { 524 for item in block.items() {
519 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 525 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
@@ -568,9 +574,16 @@ impl ExprCollector<'_> {
568 self.body.item_scope.define_def(def); 574 self.body.item_scope.define_def(def);
569 if let Some(name) = name { 575 if let Some(name) = name {
570 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 576 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
571 self.body 577 let has_constructor = match def {
572 .item_scope 578 ModuleDefId::AdtId(AdtId::StructId(s)) => {
573 .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); 579 self.db.struct_data(s).variant_data.kind() != StructKind::Record
580 }
581 _ => true,
582 };
583 self.body.item_scope.push_res(
584 name.as_name(),
585 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
586 );
574 } 587 }
575 } 588 }
576 } 589 }
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 86f953c80..09e92b74e 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -174,7 +174,7 @@ mod tests {
174 use hir_expand::{name::AsName, InFile}; 174 use hir_expand::{name::AsName, InFile};
175 use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; 175 use ra_db::{fixture::WithFixture, FileId, SourceDatabase};
176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
177 use test_utils::{assert_eq_text, covers, extract_offset}; 177 use test_utils::{assert_eq_text, extract_offset, mark};
178 178
179 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId}; 179 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId};
180 180
@@ -388,7 +388,7 @@ mod tests {
388 388
389 #[test] 389 #[test]
390 fn while_let_desugaring() { 390 fn while_let_desugaring() {
391 covers!(infer_resolve_while_let); 391 mark::check!(infer_resolve_while_let);
392 do_check_local_name( 392 do_check_local_name(
393 r#" 393 r#"
394fn test() { 394fn test() {
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 7a2067e49..e2130d931 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -9,7 +9,7 @@ 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, TypeBoundsOwner, 12 self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner,
13 VisibilityOwner, 13 VisibilityOwner,
14}; 14};
15 15
@@ -150,51 +150,31 @@ pub struct TraitData {
150 150
151impl TraitData { 151impl TraitData {
152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
153 let src = tr.lookup(db).source(db); 153 let tr_loc = tr.lookup(db);
154 let src = tr_loc.source(db);
154 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 155 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
155 let auto = src.value.auto_token().is_some(); 156 let auto = src.value.auto_token().is_some();
156 let ast_id_map = db.ast_id_map(src.file_id); 157 let module_id = tr_loc.container.module(db);
157 158
158 let container = AssocContainerId::TraitId(tr); 159 let container = AssocContainerId::TraitId(tr);
159 let items = if let Some(item_list) = src.value.item_list() { 160 let mut items = Vec::new();
160 item_list 161
161 .impl_items() 162 if let Some(item_list) = src.value.item_list() {
162 .map(|item_node| match item_node { 163 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
163 ast::ImplItem::FnDef(it) => { 164 items.extend(collect_items(
164 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 165 db,
165 let def = FunctionLoc { 166 &mut expander,
166 container, 167 item_list.assoc_items(),
167 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 168 src.file_id,
168 } 169 container,
169 .intern(db) 170 ));
170 .into(); 171 items.extend(collect_items_in_macros(
171 (name, def) 172 db,
172 } 173 &mut expander,
173 ast::ImplItem::ConstDef(it) => { 174 &src.with_value(item_list),
174 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 175 container,
175 let def = ConstLoc { 176 ));
176 container, 177 }
177 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
178 }
179 .intern(db)
180 .into();
181 (name, def)
182 }
183 ast::ImplItem::TypeAliasDef(it) => {
184 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
185 let def = TypeAliasLoc {
186 container,
187 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
188 }
189 .intern(db)
190 .into();
191 (name, def)
192 }
193 })
194 .collect()
195 } else {
196 Vec::new()
197 };
198 Arc::new(TraitData { name, items, auto }) 178 Arc::new(TraitData { name, items, auto })
199 } 179 }
200 180
@@ -232,24 +212,22 @@ impl ImplData {
232 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type()); 212 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
233 let is_negative = src.value.excl_token().is_some(); 213 let is_negative = src.value.excl_token().is_some();
234 let module_id = impl_loc.container.module(db); 214 let module_id = impl_loc.container.module(db);
215 let container = AssocContainerId::ImplId(id);
235 216
236 let mut items = Vec::new(); 217 let mut items: Vec<AssocItemId> = Vec::new();
237 218
238 if let Some(item_list) = src.value.item_list() { 219 if let Some(item_list) = src.value.item_list() {
239 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 220 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
240 items.extend(collect_impl_items( 221 items.extend(
241 db, 222 collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container)
242 &mut expander, 223 .into_iter()
243 item_list.impl_items(), 224 .map(|(_, item)| item),
244 src.file_id, 225 );
245 id, 226 items.extend(
246 )); 227 collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
247 items.extend(collect_impl_items_in_macros( 228 .into_iter()
248 db, 229 .map(|(_, item)| item),
249 &mut expander, 230 );
250 &src.with_value(item_list),
251 id,
252 ));
253 } 231 }
254 232
255 let res = ImplData { target_trait, target_type, items, is_negative }; 233 let res = ImplData { target_trait, target_type, items, is_negative };
@@ -273,11 +251,6 @@ impl ConstData {
273 Arc::new(ConstData::new(db, vis_default, node)) 251 Arc::new(ConstData::new(db, vis_default, node))
274 } 252 }
275 253
276 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<ConstData> {
277 let node = konst.lookup(db).source(db);
278 Arc::new(ConstData::new(db, RawVisibility::private(), node))
279 }
280
281 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>( 254 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(
282 db: &dyn DefDatabase, 255 db: &dyn DefDatabase,
283 vis_default: RawVisibility, 256 vis_default: RawVisibility,
@@ -292,49 +265,76 @@ impl ConstData {
292 } 265 }
293} 266}
294 267
295fn collect_impl_items_in_macros( 268#[derive(Debug, Clone, PartialEq, Eq)]
269pub struct StaticData {
270 pub name: Option<Name>,
271 pub type_ref: TypeRef,
272 pub visibility: RawVisibility,
273 pub mutable: bool,
274}
275
276impl StaticData {
277 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
278 let node = konst.lookup(db).source(db);
279 let ctx = LowerCtx::new(db, node.file_id);
280
281 let name = node.value.name().map(|n| n.as_name());
282 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
283 let mutable = node.value.mut_token().is_some();
284 let visibility = RawVisibility::from_ast_with_default(
285 db,
286 RawVisibility::private(),
287 node.map(|n| n.visibility()),
288 );
289
290 Arc::new(StaticData { name, type_ref, visibility, mutable })
291 }
292}
293
294fn collect_items_in_macros(
296 db: &dyn DefDatabase, 295 db: &dyn DefDatabase,
297 expander: &mut Expander, 296 expander: &mut Expander,
298 impl_def: &InFile<ast::ItemList>, 297 impl_def: &InFile<ast::ItemList>,
299 id: ImplId, 298 container: AssocContainerId,
300) -> Vec<AssocItemId> { 299) -> Vec<(Name, AssocItemId)> {
301 let mut res = Vec::new(); 300 let mut res = Vec::new();
302 301
303 // We set a limit to protect against infinite recursion 302 // We set a limit to protect against infinite recursion
304 let limit = 100; 303 let limit = 100;
305 304
306 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 305 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
307 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) 306 res.extend(collect_items_in_macro(db, expander, m, container, limit))
308 } 307 }
309 308
310 res 309 res
311} 310}
312 311
313fn collect_impl_items_in_macro( 312fn collect_items_in_macro(
314 db: &dyn DefDatabase, 313 db: &dyn DefDatabase,
315 expander: &mut Expander, 314 expander: &mut Expander,
316 m: ast::MacroCall, 315 m: ast::MacroCall,
317 id: ImplId, 316 container: AssocContainerId,
318 limit: usize, 317 limit: usize,
319) -> Vec<AssocItemId> { 318) -> Vec<(Name, AssocItemId)> {
320 if limit == 0 { 319 if limit == 0 {
321 return Vec::new(); 320 return Vec::new();
322 } 321 }
323 322
324 if let Some((mark, items)) = expander.enter_expand(db, None, m) { 323 if let Some((mark, items)) = expander.enter_expand(db, None, m) {
325 let items: InFile<ast::MacroItems> = expander.to_source(items); 324 let items: InFile<ast::MacroItems> = expander.to_source(items);
326 let mut res = collect_impl_items( 325 let mut res = collect_items(
327 db, 326 db,
328 expander, 327 expander,
329 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 328 items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())),
330 items.file_id, 329 items.file_id,
331 id, 330 container,
332 ); 331 );
332
333 // Recursive collect macros 333 // Recursive collect macros
334 // Note that ast::ModuleItem do not include ast::MacroCall 334 // Note that ast::ModuleItem do not include ast::MacroCall
335 // We cannot use ModuleItemOwner::items here 335 // We cannot use ModuleItemOwner::items here
336 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { 336 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
337 res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) 337 res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
338 } 338 }
339 expander.exit(db, mark); 339 expander.exit(db, mark);
340 res 340 res
@@ -343,44 +343,38 @@ fn collect_impl_items_in_macro(
343 } 343 }
344} 344}
345 345
346fn collect_impl_items( 346fn collect_items(
347 db: &dyn DefDatabase, 347 db: &dyn DefDatabase,
348 expander: &mut Expander, 348 expander: &mut Expander,
349 impl_items: impl Iterator<Item = ImplItem>, 349 assoc_items: impl Iterator<Item = AssocItem>,
350 file_id: crate::HirFileId, 350 file_id: crate::HirFileId,
351 id: ImplId, 351 container: AssocContainerId,
352) -> Vec<AssocItemId> { 352) -> Vec<(Name, AssocItemId)> {
353 let items = db.ast_id_map(file_id); 353 let items = db.ast_id_map(file_id);
354 354
355 impl_items 355 assoc_items
356 .filter_map(|item_node| match item_node { 356 .filter_map(|item_node| match item_node {
357 ast::ImplItem::FnDef(it) => { 357 ast::AssocItem::FnDef(it) => {
358 let attrs = expander.parse_attrs(&it); 358 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
359 if !expander.is_cfg_enabled(&attrs) { 359 if !expander.is_cfg_enabled(&it) {
360 return None; 360 return None;
361 } 361 }
362 let def = FunctionLoc { 362 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
363 container: AssocContainerId::ImplId(id), 363 .intern(db);
364 ast_id: AstId::new(file_id, items.ast_id(&it)), 364 Some((name, def.into()))
365 }
366 .intern(db);
367 Some(def.into())
368 } 365 }
369 ast::ImplItem::ConstDef(it) => { 366 ast::AssocItem::ConstDef(it) => {
370 let def = ConstLoc { 367 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
371 container: AssocContainerId::ImplId(id), 368 let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
372 ast_id: AstId::new(file_id, items.ast_id(&it)), 369 .intern(db);
373 } 370 Some((name, def.into()))
374 .intern(db);
375 Some(def.into())
376 } 371 }
377 ast::ImplItem::TypeAliasDef(it) => { 372 ast::AssocItem::TypeAliasDef(it) => {
378 let def = TypeAliasLoc { 373 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
379 container: AssocContainerId::ImplId(id), 374 let def =
380 ast_id: AstId::new(file_id, items.ast_id(&it)), 375 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
381 } 376 .intern(db);
382 .intern(db); 377 Some((name, def.into()))
383 Some(def.into())
384 } 378 }
385 }) 379 })
386 .collect() 380 .collect()
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 5dc7395f5..945a0025e 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -1,7 +1,7 @@
1//! Defines database & queries for name resolution. 1//! Defines database & queries for name resolution.
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_expand::{db::AstDatabase, HirFileId}; 4use hir_expand::{db::AstDatabase, name::Name, HirFileId};
5use ra_db::{salsa, CrateId, SourceDatabase, Upcast}; 5use ra_db::{salsa, CrateId, SourceDatabase, Upcast};
6use ra_prof::profile; 6use ra_prof::profile;
7use ra_syntax::SmolStr; 7use ra_syntax::SmolStr;
@@ -10,11 +10,15 @@ use crate::{
10 adt::{EnumData, StructData}, 10 adt::{EnumData, StructData},
11 attr::Attrs, 11 attr::Attrs,
12 body::{scope::ExprScopes, Body, BodySourceMap}, 12 body::{scope::ExprScopes, Body, BodySourceMap},
13 data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData}, 13 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData},
14 docs::Documentation, 14 docs::Documentation,
15 find_path,
15 generics::GenericParams, 16 generics::GenericParams,
17 item_scope::ItemInNs,
16 lang_item::{LangItemTarget, LangItems}, 18 lang_item::{LangItemTarget, LangItems},
17 nameres::{raw::RawItems, CrateDefMap}, 19 nameres::{raw::RawItems, CrateDefMap},
20 path::ModPath,
21 visibility::Visibility,
18 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, 22 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc,
19 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, 23 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId,
20 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, 24 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
@@ -77,8 +81,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
77 #[salsa::invoke(ConstData::const_data_query)] 81 #[salsa::invoke(ConstData::const_data_query)]
78 fn const_data(&self, konst: ConstId) -> Arc<ConstData>; 82 fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
79 83
80 #[salsa::invoke(ConstData::static_data_query)] 84 #[salsa::invoke(StaticData::static_data_query)]
81 fn static_data(&self, konst: StaticId) -> Arc<ConstData>; 85 fn static_data(&self, konst: StaticId) -> Arc<StaticData>;
82 86
83 #[salsa::invoke(Body::body_with_source_map_query)] 87 #[salsa::invoke(Body::body_with_source_map_query)]
84 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 88 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
@@ -108,6 +112,16 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
108 // Remove this query completely, in favor of `Attrs::docs` method 112 // Remove this query completely, in favor of `Attrs::docs` method
109 #[salsa::invoke(Documentation::documentation_query)] 113 #[salsa::invoke(Documentation::documentation_query)]
110 fn documentation(&self, def: AttrDefId) -> Option<Documentation>; 114 fn documentation(&self, def: AttrDefId) -> Option<Documentation>;
115
116 #[salsa::invoke(find_path::importable_locations_of_query)]
117 fn importable_locations_of(
118 &self,
119 item: ItemInNs,
120 krate: CrateId,
121 ) -> Arc<[(ModuleId, Name, Visibility)]>;
122
123 #[salsa::invoke(find_path::find_path_inner_query)]
124 fn find_path_inner(&self, item: ItemInNs, from: ModuleId, max_len: usize) -> Option<ModPath>;
111} 125}
112 126
113fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { 127fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> {
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index aad12e123..a0cdad529 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -101,6 +101,9 @@ pub enum Expr {
101 Try { 101 Try {
102 expr: ExprId, 102 expr: ExprId,
103 }, 103 },
104 TryBlock {
105 body: ExprId,
106 },
104 Cast { 107 Cast {
105 expr: ExprId, 108 expr: ExprId,
106 type_ref: TypeRef, 109 type_ref: TypeRef,
@@ -236,6 +239,7 @@ impl Expr {
236 f(*expr); 239 f(*expr);
237 } 240 }
238 } 241 }
242 Expr::TryBlock { body } => f(*body),
239 Expr::Loop { body } => f(*body), 243 Expr::Loop { body } => f(*body),
240 Expr::While { condition, body } => { 244 Expr::While { condition, body } => {
241 f(*condition); 245 f(*condition);
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs
index 70dcb03e6..4db798473 100644
--- a/crates/ra_hir_def/src/find_path.rs
+++ b/crates/ra_hir_def/src/find_path.rs
@@ -1,5 +1,11 @@
1//! An algorithm to find a path to refer to a certain item. 1//! An algorithm to find a path to refer to a certain item.
2 2
3use std::sync::Arc;
4
5use hir_expand::name::{known, AsName, Name};
6use ra_prof::profile;
7use test_utils::mark;
8
3use crate::{ 9use crate::{
4 db::DefDatabase, 10 db::DefDatabase,
5 item_scope::ItemInNs, 11 item_scope::ItemInNs,
@@ -7,25 +13,28 @@ use crate::{
7 visibility::Visibility, 13 visibility::Visibility,
8 CrateId, ModuleDefId, ModuleId, 14 CrateId, ModuleDefId, ModuleId,
9}; 15};
10use hir_expand::name::{known, AsName, Name}; 16
11use test_utils::tested_by; 17// FIXME: handle local items
18
19/// Find a path that can be used to refer to a certain item. This can depend on
20/// *from where* you're referring to the item, hence the `from` parameter.
21pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
22 let _p = profile("find_path");
23 db.find_path_inner(item, from, MAX_PATH_LEN)
24}
12 25
13const MAX_PATH_LEN: usize = 15; 26const MAX_PATH_LEN: usize = 15;
14 27
15impl ModPath { 28impl ModPath {
16 fn starts_with_std(&self) -> bool { 29 fn starts_with_std(&self) -> bool {
17 self.segments.first().filter(|&first_segment| first_segment == &known::std).is_some() 30 self.segments.first() == Some(&known::std)
18 } 31 }
19 32
20 // When std library is present, paths starting with `std::` 33 // When std library is present, paths starting with `std::`
21 // should be preferred over paths starting with `core::` and `alloc::` 34 // should be preferred over paths starting with `core::` and `alloc::`
22 fn can_start_with_std(&self) -> bool { 35 fn can_start_with_std(&self) -> bool {
23 self.segments 36 let first_segment = self.segments.first();
24 .first() 37 first_segment == Some(&known::alloc) || first_segment == Some(&known::core)
25 .filter(|&first_segment| {
26 first_segment == &known::alloc || first_segment == &known::core
27 })
28 .is_some()
29 } 38 }
30 39
31 fn len(&self) -> usize { 40 fn len(&self) -> usize {
@@ -40,15 +49,7 @@ impl ModPath {
40 } 49 }
41} 50}
42 51
43// FIXME: handle local items 52pub(crate) fn find_path_inner_query(
44
45/// Find a path that can be used to refer to a certain item. This can depend on
46/// *from where* you're referring to the item, hence the `from` parameter.
47pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
48 find_path_inner(db, item, from, MAX_PATH_LEN)
49}
50
51fn find_path_inner(
52 db: &dyn DefDatabase, 53 db: &dyn DefDatabase,
53 item: ItemInNs, 54 item: ItemInNs,
54 from: ModuleId, 55 from: ModuleId,
@@ -139,8 +140,7 @@ fn find_path_inner(
139 let mut best_path = None; 140 let mut best_path = None;
140 let mut best_path_len = max_len; 141 let mut best_path_len = max_len;
141 for (module_id, name) in importable_locations { 142 for (module_id, name) in importable_locations {
142 let mut path = match find_path_inner( 143 let mut path = match db.find_path_inner(
143 db,
144 ItemInNs::Types(ModuleDefId::ModuleId(module_id)), 144 ItemInNs::Types(ModuleDefId::ModuleId(module_id)),
145 from, 145 from,
146 best_path_len - 1, 146 best_path_len - 1,
@@ -163,17 +163,19 @@ fn find_path_inner(
163 163
164fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath { 164fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath {
165 if old_path.starts_with_std() && new_path.can_start_with_std() { 165 if old_path.starts_with_std() && new_path.can_start_with_std() {
166 tested_by!(prefer_std_paths);
167 if prefer_no_std { 166 if prefer_no_std {
167 mark::hit!(prefer_no_std_paths);
168 new_path 168 new_path
169 } else { 169 } else {
170 mark::hit!(prefer_std_paths);
170 old_path 171 old_path
171 } 172 }
172 } else if new_path.starts_with_std() && old_path.can_start_with_std() { 173 } else if new_path.starts_with_std() && old_path.can_start_with_std() {
173 tested_by!(prefer_std_paths);
174 if prefer_no_std { 174 if prefer_no_std {
175 mark::hit!(prefer_no_std_paths);
175 old_path 176 old_path
176 } else { 177 } else {
178 mark::hit!(prefer_std_paths);
177 new_path 179 new_path
178 } 180 }
179 } else if new_path.len() < old_path.len() { 181 } else if new_path.len() < old_path.len() {
@@ -198,7 +200,7 @@ fn find_importable_locations(
198 .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id)) 200 .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id))
199 { 201 {
200 result.extend( 202 result.extend(
201 importable_locations_in_crate(db, item, krate) 203 db.importable_locations_of(item, krate)
202 .iter() 204 .iter()
203 .filter(|(_, _, vis)| vis.is_visible_from(db, from)) 205 .filter(|(_, _, vis)| vis.is_visible_from(db, from))
204 .map(|(m, n, _)| (*m, n.clone())), 206 .map(|(m, n, _)| (*m, n.clone())),
@@ -213,11 +215,12 @@ fn find_importable_locations(
213/// 215///
214/// Note that the crate doesn't need to be the one in which the item is defined; 216/// Note that the crate doesn't need to be the one in which the item is defined;
215/// it might be re-exported in other crates. 217/// it might be re-exported in other crates.
216fn importable_locations_in_crate( 218pub(crate) fn importable_locations_of_query(
217 db: &dyn DefDatabase, 219 db: &dyn DefDatabase,
218 item: ItemInNs, 220 item: ItemInNs,
219 krate: CrateId, 221 krate: CrateId,
220) -> Vec<(ModuleId, Name, Visibility)> { 222) -> Arc<[(ModuleId, Name, Visibility)]> {
223 let _p = profile("importable_locations_of_query");
221 let def_map = db.crate_def_map(krate); 224 let def_map = db.crate_def_map(krate);
222 let mut result = Vec::new(); 225 let mut result = Vec::new();
223 for (local_id, data) in def_map.modules.iter() { 226 for (local_id, data) in def_map.modules.iter() {
@@ -243,17 +246,20 @@ fn importable_locations_in_crate(
243 result.push((ModuleId { krate, local_id }, name.clone(), vis)); 246 result.push((ModuleId { krate, local_id }, name.clone(), vis));
244 } 247 }
245 } 248 }
246 result 249
250 Arc::from(result)
247} 251}
248 252
249#[cfg(test)] 253#[cfg(test)]
250mod tests { 254mod tests {
251 use super::*;
252 use crate::test_db::TestDB;
253 use hir_expand::hygiene::Hygiene; 255 use hir_expand::hygiene::Hygiene;
254 use ra_db::fixture::WithFixture; 256 use ra_db::fixture::WithFixture;
255 use ra_syntax::ast::AstNode; 257 use ra_syntax::ast::AstNode;
256 use test_utils::covers; 258 use test_utils::mark;
259
260 use crate::test_db::TestDB;
261
262 use super::*;
257 263
258 /// `code` needs to contain a cursor marker; checks that `find_path` for the 264 /// `code` needs to contain a cursor marker; checks that `find_path` for the
259 /// item the `path` refers to returns that same path when called from the 265 /// item the `path` refers to returns that same path when called from the
@@ -508,7 +514,7 @@ mod tests {
508 514
509 #[test] 515 #[test]
510 fn prefer_std_paths_over_alloc() { 516 fn prefer_std_paths_over_alloc() {
511 covers!(prefer_std_paths); 517 mark::check!(prefer_std_paths);
512 let code = r#" 518 let code = r#"
513 //- /main.rs crate:main deps:alloc,std 519 //- /main.rs crate:main deps:alloc,std
514 <|> 520 <|>
@@ -527,51 +533,50 @@ mod tests {
527 } 533 }
528 534
529 #[test] 535 #[test]
530 fn prefer_alloc_paths_over_std() { 536 fn prefer_core_paths_over_std() {
531 covers!(prefer_std_paths); 537 mark::check!(prefer_no_std_paths);
532 let code = r#" 538 let code = r#"
533 //- /main.rs crate:main deps:alloc,std 539 //- /main.rs crate:main deps:core,std
534 #![no_std] 540 #![no_std]
535 541
536 <|> 542 <|>
537 543
538 //- /std.rs crate:std deps:alloc 544 //- /std.rs crate:std deps:core
539 545
540 pub mod sync { 546 pub mod fmt {
541 pub use alloc::sync::Arc; 547 pub use core::fmt::Error;
542 } 548 }
543 549
544 //- /zzz.rs crate:alloc 550 //- /zzz.rs crate:core
545 551
546 pub mod sync { 552 pub mod fmt {
547 pub struct Arc; 553 pub struct Error;
548 } 554 }
549 "#; 555 "#;
550 check_found_path(code, "alloc::sync::Arc"); 556 check_found_path(code, "core::fmt::Error");
551 } 557 }
552 558
553 #[test] 559 #[test]
554 fn prefer_core_paths_over_std() { 560 fn prefer_alloc_paths_over_std() {
555 covers!(prefer_std_paths);
556 let code = r#" 561 let code = r#"
557 //- /main.rs crate:main deps:core,std 562 //- /main.rs crate:main deps:alloc,std
558 #![no_std] 563 #![no_std]
559 564
560 <|> 565 <|>
561 566
562 //- /std.rs crate:std deps:core 567 //- /std.rs crate:std deps:alloc
563 568
564 pub mod fmt { 569 pub mod sync {
565 pub use core::fmt::Error; 570 pub use alloc::sync::Arc;
566 } 571 }
567 572
568 //- /zzz.rs crate:core 573 //- /zzz.rs crate:alloc
569 574
570 pub mod fmt { 575 pub mod sync {
571 pub struct Error; 576 pub struct Arc;
572 } 577 }
573 "#; 578 "#;
574 check_found_path(code, "core::fmt::Error"); 579 check_found_path(code, "alloc::sync::Arc");
575 } 580 }
576 581
577 #[test] 582 #[test]
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
index 259b9ff03..fc15948ad 100644
--- a/crates/ra_hir_def/src/item_scope.rs
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -151,13 +151,20 @@ impl ItemScope {
151} 151}
152 152
153impl PerNs { 153impl PerNs {
154 pub(crate) fn from_def(def: ModuleDefId, v: Visibility) -> PerNs { 154 pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs {
155 match def { 155 match def {
156 ModuleDefId::ModuleId(_) => PerNs::types(def, v), 156 ModuleDefId::ModuleId(_) => PerNs::types(def, v),
157 ModuleDefId::FunctionId(_) => PerNs::values(def, v), 157 ModuleDefId::FunctionId(_) => PerNs::values(def, v),
158 ModuleDefId::AdtId(adt) => match adt { 158 ModuleDefId::AdtId(adt) => match adt {
159 AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def, v), 159 AdtId::UnionId(_) => PerNs::types(def, v),
160 AdtId::EnumId(_) => PerNs::types(def, v), 160 AdtId::EnumId(_) => PerNs::types(def, v),
161 AdtId::StructId(_) => {
162 if has_constructor {
163 PerNs::both(def, def, v)
164 } else {
165 PerNs::types(def, v)
166 }
167 }
161 }, 168 },
162 ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), 169 ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v),
163 ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), 170 ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v),
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 518772e8a..5325a2760 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -46,8 +46,6 @@ pub mod find_path;
46 46
47#[cfg(test)] 47#[cfg(test)]
48mod test_db; 48mod test_db;
49#[cfg(test)]
50mod marks;
51 49
52use std::hash::Hash; 50use std::hash::Hash;
53 51
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs
deleted file mode 100644
index daa49d5f1..000000000
--- a/crates/ra_hir_def/src/marks.rs
+++ /dev/null
@@ -1,17 +0,0 @@
1//! See test_utils/src/marks.rs
2
3test_utils::marks!(
4 bogus_paths
5 name_res_works_for_broken_modules
6 can_import_enum_variant
7 glob_enum
8 glob_enum_group
9 glob_across_crates
10 std_prelude
11 macro_rules_from_other_crates_are_visible_with_macro_use
12 prelude_is_macro_use
13 macro_dollar_crate_self
14 macro_dollar_crate_other
15 infer_resolve_while_let
16 prefer_std_paths
17);
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 98c74fe25..353a31ad4 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -14,7 +14,7 @@ use ra_cfg::CfgOptions;
14use ra_db::{CrateId, FileId, ProcMacroId}; 14use ra_db::{CrateId, FileId, ProcMacroId};
15use ra_syntax::ast; 15use ra_syntax::ast;
16use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
17use test_utils::tested_by; 17use test_utils::mark;
18 18
19use crate::{ 19use crate::{
20 attr::Attrs, 20 attr::Attrs,
@@ -204,6 +204,7 @@ impl DefCollector<'_> {
204 ast_id: None, 204 ast_id: None,
205 krate: Some(krate), 205 krate: Some(krate),
206 kind: MacroDefKind::CustomDerive(expander), 206 kind: MacroDefKind::CustomDerive(expander),
207 local_inner: false,
207 }; 208 };
208 209
209 self.define_proc_macro(name.clone(), macro_id); 210 self.define_proc_macro(name.clone(), macro_id);
@@ -301,7 +302,7 @@ impl DefCollector<'_> {
301 ); 302 );
302 303
303 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { 304 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
304 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use); 305 mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
305 self.import_all_macros_exported(current_module_id, m.krate); 306 self.import_all_macros_exported(current_module_id, m.krate);
306 } 307 }
307 } 308 }
@@ -411,10 +412,10 @@ impl DefCollector<'_> {
411 match def.take_types() { 412 match def.take_types() {
412 Some(ModuleDefId::ModuleId(m)) => { 413 Some(ModuleDefId::ModuleId(m)) => {
413 if import.is_prelude { 414 if import.is_prelude {
414 tested_by!(std_prelude); 415 mark::hit!(std_prelude);
415 self.def_map.prelude = Some(m); 416 self.def_map.prelude = Some(m);
416 } else if m.krate != self.def_map.krate { 417 } else if m.krate != self.def_map.krate {
417 tested_by!(glob_across_crates); 418 mark::hit!(glob_across_crates);
418 // glob import from other crate => we can just import everything once 419 // glob import from other crate => we can just import everything once
419 let item_map = self.db.crate_def_map(m.krate); 420 let item_map = self.db.crate_def_map(m.krate);
420 let scope = &item_map[m.local_id].scope; 421 let scope = &item_map[m.local_id].scope;
@@ -460,7 +461,7 @@ impl DefCollector<'_> {
460 } 461 }
461 } 462 }
462 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { 463 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
463 tested_by!(glob_enum); 464 mark::hit!(glob_enum);
464 // glob import from enum => just import all the variants 465 // glob import from enum => just import all the variants
465 466
466 // XXX: urgh, so this works by accident! Here, we look at 467 // XXX: urgh, so this works by accident! Here, we look at
@@ -509,7 +510,7 @@ impl DefCollector<'_> {
509 510
510 self.update(module_id, &[(name, def)], vis); 511 self.update(module_id, &[(name, def)], vis);
511 } 512 }
512 None => tested_by!(bogus_paths), 513 None => mark::hit!(bogus_paths),
513 } 514 }
514 } 515 }
515 } 516 }
@@ -682,7 +683,7 @@ impl ModCollector<'_, '_> {
682 // Prelude module is always considered to be `#[macro_use]`. 683 // Prelude module is always considered to be `#[macro_use]`.
683 if let Some(prelude_module) = self.def_collector.def_map.prelude { 684 if let Some(prelude_module) = self.def_collector.def_map.prelude {
684 if prelude_module.krate != self.def_collector.def_map.krate { 685 if prelude_module.krate != self.def_collector.def_map.krate {
685 tested_by!(prelude_is_macro_use); 686 mark::hit!(prelude_is_macro_use);
686 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate); 687 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
687 } 688 }
688 } 689 }
@@ -829,7 +830,7 @@ impl ModCollector<'_, '_> {
829 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; 830 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res };
830 let def: ModuleDefId = module.into(); 831 let def: ModuleDefId = module.into();
831 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 832 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
832 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis); 833 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis, false))], vis);
833 res 834 res
834 } 835 }
835 836
@@ -843,6 +844,8 @@ impl ModCollector<'_, '_> {
843 let name = def.name.clone(); 844 let name = def.name.clone();
844 let container = ContainerId::ModuleId(module); 845 let container = ContainerId::ModuleId(module);
845 let vis = &def.visibility; 846 let vis = &def.visibility;
847 let mut has_constructor = false;
848
846 let def: ModuleDefId = match def.kind { 849 let def: ModuleDefId = match def.kind {
847 raw::DefKind::Function(ast_id) => FunctionLoc { 850 raw::DefKind::Function(ast_id) => FunctionLoc {
848 container: container.into(), 851 container: container.into(),
@@ -850,7 +853,8 @@ impl ModCollector<'_, '_> {
850 } 853 }
851 .intern(self.def_collector.db) 854 .intern(self.def_collector.db)
852 .into(), 855 .into(),
853 raw::DefKind::Struct(ast_id) => { 856 raw::DefKind::Struct(ast_id, mode) => {
857 has_constructor = mode != raw::StructDefKind::Record;
854 StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } 858 StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
855 .intern(self.def_collector.db) 859 .intern(self.def_collector.db)
856 .into() 860 .into()
@@ -893,7 +897,11 @@ impl ModCollector<'_, '_> {
893 .def_map 897 .def_map
894 .resolve_visibility(self.def_collector.db, self.module_id, vis) 898 .resolve_visibility(self.def_collector.db, self.module_id, vis)
895 .unwrap_or(Visibility::Public); 899 .unwrap_or(Visibility::Public);
896 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis) 900 self.def_collector.update(
901 self.module_id,
902 &[(name, PerNs::from_def(def, vis, has_constructor))],
903 vis,
904 )
897 } 905 }
898 906
899 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { 907 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
@@ -941,6 +949,7 @@ impl ModCollector<'_, '_> {
941 ast_id: Some(ast_id.ast_id), 949 ast_id: Some(ast_id.ast_id),
942 krate: Some(self.def_collector.def_map.krate), 950 krate: Some(self.def_collector.def_map.krate),
943 kind: MacroDefKind::Declarative, 951 kind: MacroDefKind::Declarative,
952 local_inner: mac.local_inner,
944 }; 953 };
945 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); 954 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
946 } 955 }
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 35a0a0c98..19692e70c 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -14,7 +14,7 @@ use std::iter::successors;
14 14
15use hir_expand::name::Name; 15use hir_expand::name::Name;
16use ra_db::Edition; 16use ra_db::Edition;
17use test_utils::tested_by; 17use test_utils::mark;
18 18
19use crate::{ 19use crate::{
20 db::DefDatabase, 20 db::DefDatabase,
@@ -108,7 +108,7 @@ impl CrateDefMap {
108 let mut curr_per_ns: PerNs = match path.kind { 108 let mut curr_per_ns: PerNs = match path.kind {
109 PathKind::DollarCrate(krate) => { 109 PathKind::DollarCrate(krate) => {
110 if krate == self.krate { 110 if krate == self.krate {
111 tested_by!(macro_dollar_crate_self); 111 mark::hit!(macro_dollar_crate_self);
112 PerNs::types( 112 PerNs::types(
113 ModuleId { krate: self.krate, local_id: self.root }.into(), 113 ModuleId { krate: self.krate, local_id: self.root }.into(),
114 Visibility::Public, 114 Visibility::Public,
@@ -116,7 +116,7 @@ impl CrateDefMap {
116 } else { 116 } else {
117 let def_map = db.crate_def_map(krate); 117 let def_map = db.crate_def_map(krate);
118 let module = ModuleId { krate, local_id: def_map.root }; 118 let module = ModuleId { krate, local_id: def_map.root };
119 tested_by!(macro_dollar_crate_other); 119 mark::hit!(macro_dollar_crate_other);
120 PerNs::types(module.into(), Visibility::Public) 120 PerNs::types(module.into(), Visibility::Public)
121 } 121 }
122 } 122 }
@@ -221,7 +221,7 @@ impl CrateDefMap {
221 } 221 }
222 ModuleDefId::AdtId(AdtId::EnumId(e)) => { 222 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
223 // enum variant 223 // enum variant
224 tested_by!(can_import_enum_variant); 224 mark::hit!(can_import_enum_variant);
225 let enum_data = db.enum_data(e); 225 let enum_data = db.enum_data(e);
226 match enum_data.variant(&segment) { 226 match enum_data.variant(&segment) {
227 Some(local_id) => { 227 Some(local_id) => {
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 39b011ad7..4e628b14d 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -18,7 +18,7 @@ use ra_syntax::{
18 ast::{self, AttrsOwner, NameOwner, VisibilityOwner}, 18 ast::{self, AttrsOwner, NameOwner, VisibilityOwner},
19 AstNode, 19 AstNode,
20}; 20};
21use test_utils::tested_by; 21use test_utils::mark;
22 22
23use crate::{ 23use crate::{
24 attr::Attrs, 24 attr::Attrs,
@@ -156,9 +156,16 @@ pub(super) struct DefData {
156} 156}
157 157
158#[derive(Debug, PartialEq, Eq, Clone, Copy)] 158#[derive(Debug, PartialEq, Eq, Clone, Copy)]
159pub(super) enum StructDefKind {
160 Record,
161 Tuple,
162 Unit,
163}
164
165#[derive(Debug, PartialEq, Eq, Clone, Copy)]
159pub(super) enum DefKind { 166pub(super) enum DefKind {
160 Function(FileAstId<ast::FnDef>), 167 Function(FileAstId<ast::FnDef>),
161 Struct(FileAstId<ast::StructDef>), 168 Struct(FileAstId<ast::StructDef>, StructDefKind),
162 Union(FileAstId<ast::UnionDef>), 169 Union(FileAstId<ast::UnionDef>),
163 Enum(FileAstId<ast::EnumDef>), 170 Enum(FileAstId<ast::EnumDef>),
164 Const(FileAstId<ast::ConstDef>), 171 Const(FileAstId<ast::ConstDef>),
@@ -171,7 +178,7 @@ impl DefKind {
171 pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> { 178 pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> {
172 match self { 179 match self {
173 DefKind::Function(it) => it.upcast(), 180 DefKind::Function(it) => it.upcast(),
174 DefKind::Struct(it) => it.upcast(), 181 DefKind::Struct(it, _) => it.upcast(),
175 DefKind::Union(it) => it.upcast(), 182 DefKind::Union(it) => it.upcast(),
176 DefKind::Enum(it) => it.upcast(), 183 DefKind::Enum(it) => it.upcast(),
177 DefKind::Const(it) => it.upcast(), 184 DefKind::Const(it) => it.upcast(),
@@ -188,6 +195,7 @@ pub(super) struct MacroData {
188 pub(super) path: ModPath, 195 pub(super) path: ModPath,
189 pub(super) name: Option<Name>, 196 pub(super) name: Option<Name>,
190 pub(super) export: bool, 197 pub(super) export: bool,
198 pub(super) local_inner: bool,
191 pub(super) builtin: bool, 199 pub(super) builtin: bool,
192} 200}
193 201
@@ -235,9 +243,14 @@ impl RawItemsCollector {
235 return; 243 return;
236 } 244 }
237 ast::ModuleItem::StructDef(it) => { 245 ast::ModuleItem::StructDef(it) => {
246 let kind = match it.kind() {
247 ast::StructKind::Record(_) => StructDefKind::Record,
248 ast::StructKind::Tuple(_) => StructDefKind::Tuple,
249 ast::StructKind::Unit => StructDefKind::Unit,
250 };
238 let id = self.source_ast_id_map.ast_id(&it); 251 let id = self.source_ast_id_map.ast_id(&it);
239 let name = it.name(); 252 let name = it.name();
240 (DefKind::Struct(id), name) 253 (DefKind::Struct(id, kind), name)
241 } 254 }
242 ast::ModuleItem::UnionDef(it) => { 255 ast::ModuleItem::UnionDef(it) => {
243 let id = self.source_ast_id_map.ast_id(&it); 256 let id = self.source_ast_id_map.ast_id(&it);
@@ -333,7 +346,7 @@ impl RawItemsCollector {
333 self.push_item(current_module, attrs, RawItemKind::Module(item)); 346 self.push_item(current_module, attrs, RawItemKind::Module(item));
334 return; 347 return;
335 } 348 }
336 tested_by!(name_res_works_for_broken_modules); 349 mark::hit!(name_res_works_for_broken_modules);
337 } 350 }
338 351
339 fn add_use_item(&mut self, current_module: Option<Idx<ModuleData>>, use_item: ast::UseItem) { 352 fn add_use_item(&mut self, current_module: Option<Idx<ModuleData>>, use_item: ast::UseItem) {
@@ -401,14 +414,32 @@ impl RawItemsCollector {
401 414
402 let name = m.name().map(|it| it.as_name()); 415 let name = m.name().map(|it| it.as_name());
403 let ast_id = self.source_ast_id_map.ast_id(&m); 416 let ast_id = self.source_ast_id_map.ast_id(&m);
404 // FIXME: cfg_attr
405 let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
406 417
407 // FIXME: cfg_attr 418 // FIXME: cfg_attr
408 let builtin = 419 let export_attr = attrs.by_key("macro_export");
409 m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "rustc_builtin_macro"); 420
421 let export = export_attr.exists();
422 let local_inner = if export {
423 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
424 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
425 ident.text.contains("local_inner_macros")
426 }
427 _ => false,
428 })
429 } else {
430 false
431 };
432
433 let builtin = attrs.by_key("rustc_builtin_macro").exists();
410 434
411 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export, builtin }); 435 let m = self.raw_items.macros.alloc(MacroData {
436 ast_id,
437 path,
438 name,
439 export,
440 local_inner,
441 builtin,
442 });
412 self.push_item(current_module, attrs, RawItemKind::Macro(m)); 443 self.push_item(current_module, attrs, RawItemKind::Macro(m));
413 } 444 }
414 445
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 83120fa36..05cd0297d 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -8,7 +8,7 @@ use std::sync::Arc;
8 8
9use insta::assert_snapshot; 9use insta::assert_snapshot;
10use ra_db::{fixture::WithFixture, SourceDatabase}; 10use ra_db::{fixture::WithFixture, SourceDatabase};
11use test_utils::covers; 11use test_utils::mark;
12 12
13use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; 13use crate::{db::DefDatabase, nameres::*, test_db::TestDB};
14 14
@@ -67,7 +67,7 @@ fn crate_def_map_smoke_test() {
67 ⋮Baz: t v 67 ⋮Baz: t v
68 ⋮E: t 68 ⋮E: t
69 ⋮EXT: v 69 ⋮EXT: v
70 ⋮U: t v 70 ⋮U: t
71 ⋮ext: v 71 ⋮ext: v
72 "###) 72 "###)
73} 73}
@@ -132,7 +132,7 @@ fn crate_def_map_fn_mod_same_name() {
132 132
133#[test] 133#[test]
134fn bogus_paths() { 134fn bogus_paths() {
135 covers!(bogus_paths); 135 mark::check!(bogus_paths);
136 let map = def_map( 136 let map = def_map(
137 " 137 "
138 //- /lib.rs 138 //- /lib.rs
@@ -247,7 +247,7 @@ fn re_exports() {
247 247
248#[test] 248#[test]
249fn std_prelude() { 249fn std_prelude() {
250 covers!(std_prelude); 250 mark::check!(std_prelude);
251 let map = def_map( 251 let map = def_map(
252 " 252 "
253 //- /main.rs crate:main deps:test_crate 253 //- /main.rs crate:main deps:test_crate
@@ -271,7 +271,7 @@ fn std_prelude() {
271 271
272#[test] 272#[test]
273fn can_import_enum_variant() { 273fn can_import_enum_variant() {
274 covers!(can_import_enum_variant); 274 mark::check!(can_import_enum_variant);
275 let map = def_map( 275 let map = def_map(
276 " 276 "
277 //- /lib.rs 277 //- /lib.rs
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs
index ee8df3a26..2b12c0daa 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir_def/src/nameres/tests/globs.rs
@@ -152,7 +152,7 @@ fn glob_privacy_2() {
152 152
153#[test] 153#[test]
154fn glob_across_crates() { 154fn glob_across_crates() {
155 covers!(glob_across_crates); 155 mark::check!(glob_across_crates);
156 let map = def_map( 156 let map = def_map(
157 r" 157 r"
158 //- /main.rs crate:main deps:test_crate 158 //- /main.rs crate:main deps:test_crate
@@ -171,7 +171,6 @@ fn glob_across_crates() {
171 171
172#[test] 172#[test]
173fn glob_privacy_across_crates() { 173fn glob_privacy_across_crates() {
174 covers!(glob_across_crates);
175 let map = def_map( 174 let map = def_map(
176 r" 175 r"
177 //- /main.rs crate:main deps:test_crate 176 //- /main.rs crate:main deps:test_crate
@@ -191,7 +190,7 @@ fn glob_privacy_across_crates() {
191 190
192#[test] 191#[test]
193fn glob_enum() { 192fn glob_enum() {
194 covers!(glob_enum); 193 mark::check!(glob_enum);
195 let map = def_map( 194 let map = def_map(
196 " 195 "
197 //- /lib.rs 196 //- /lib.rs
@@ -212,7 +211,7 @@ fn glob_enum() {
212 211
213#[test] 212#[test]
214fn glob_enum_group() { 213fn glob_enum_group() {
215 covers!(glob_enum_group); 214 mark::check!(glob_enum_group);
216 let map = def_map( 215 let map = def_map(
217 r" 216 r"
218 //- /lib.rs 217 //- /lib.rs
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs
index b0befdfbd..84480d9f6 100644
--- a/crates/ra_hir_def/src/nameres/tests/macros.rs
+++ b/crates/ra_hir_def/src/nameres/tests/macros.rs
@@ -19,12 +19,12 @@ fn macro_rules_are_globally_visible() {
19 ); 19 );
20 assert_snapshot!(map, @r###" 20 assert_snapshot!(map, @r###"
21 ⋮crate 21 ⋮crate
22 ⋮Foo: t v 22 ⋮Foo: t
23 ⋮nested: t 23 ⋮nested: t
24 24
25 ⋮crate::nested 25 ⋮crate::nested
26 ⋮Bar: t v 26 ⋮Bar: t
27 ⋮Baz: t v 27 ⋮Baz: t
28 "###); 28 "###);
29} 29}
30 30
@@ -91,13 +91,13 @@ fn macro_rules_from_other_crates_are_visible() {
91 ); 91 );
92 assert_snapshot!(map, @r###" 92 assert_snapshot!(map, @r###"
93 ⋮crate 93 ⋮crate
94 ⋮Bar: t v 94 ⋮Bar: t
95 ⋮Foo: t v 95 ⋮Foo: t
96 ⋮bar: t 96 ⋮bar: t
97 97
98 ⋮crate::bar 98 ⋮crate::bar
99 ⋮Bar: t v 99 ⋮Bar: t
100 ⋮Foo: t v 100 ⋮Foo: t
101 ⋮bar: t 101 ⋮bar: t
102 "###); 102 "###);
103} 103}
@@ -124,13 +124,50 @@ fn macro_rules_export_with_local_inner_macros_are_visible() {
124 ); 124 );
125 assert_snapshot!(map, @r###" 125 assert_snapshot!(map, @r###"
126 ⋮crate 126 ⋮crate
127 ⋮Bar: t v 127 ⋮Bar: t
128 ⋮Foo: t v 128 ⋮Foo: t
129 ⋮bar: t 129 ⋮bar: t
130 130
131 ⋮crate::bar 131 ⋮crate::bar
132 ⋮Bar: t v 132 ⋮Bar: t
133 ⋮Foo: t v 133 ⋮Foo: t
134 ⋮bar: t
135 "###);
136}
137
138#[test]
139fn local_inner_macros_makes_local_macros_usable() {
140 let map = def_map(
141 "
142 //- /main.rs crate:main deps:foo
143 foo::structs!(Foo, Bar);
144 mod bar;
145 //- /bar.rs
146 use crate::*;
147 //- /lib.rs crate:foo
148 #[macro_export(local_inner_macros)]
149 macro_rules! structs {
150 ($($i:ident),*) => {
151 inner!($($i),*);
152 }
153 }
154 #[macro_export]
155 macro_rules! inner {
156 ($($i:ident),*) => {
157 $(struct $i { field: u32 } )*
158 }
159 }
160 ",
161 );
162 assert_snapshot!(map, @r###"
163 ⋮crate
164 ⋮Bar: t
165 ⋮Foo: t
166 ⋮bar: t
167
168 ⋮crate::bar
169 ⋮Bar: t
170 ⋮Foo: t
134 ⋮bar: t 171 ⋮bar: t
135 "###); 172 "###);
136} 173}
@@ -167,7 +204,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
167 ); 204 );
168 assert_snapshot!(map, @r###" 205 assert_snapshot!(map, @r###"
169 ⋮crate 206 ⋮crate
170 ⋮Foo: t v 207 ⋮Foo: t
171 ⋮bar: m 208 ⋮bar: m
172 ⋮foo: m 209 ⋮foo: m
173 "###); 210 "###);
@@ -175,7 +212,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
175 212
176#[test] 213#[test]
177fn macro_rules_from_other_crates_are_visible_with_macro_use() { 214fn macro_rules_from_other_crates_are_visible_with_macro_use() {
178 covers!(macro_rules_from_other_crates_are_visible_with_macro_use); 215 mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use);
179 let map = def_map( 216 let map = def_map(
180 " 217 "
181 //- /main.rs crate:main deps:foo 218 //- /main.rs crate:main deps:foo
@@ -225,7 +262,7 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
225 262
226#[test] 263#[test]
227fn prelude_is_macro_use() { 264fn prelude_is_macro_use() {
228 covers!(prelude_is_macro_use); 265 mark::check!(prelude_is_macro_use);
229 let map = def_map( 266 let map = def_map(
230 " 267 "
231 //- /main.rs crate:main deps:foo 268 //- /main.rs crate:main deps:foo
@@ -507,8 +544,7 @@ fn path_qualified_macros() {
507 544
508#[test] 545#[test]
509fn macro_dollar_crate_is_correct_in_item() { 546fn macro_dollar_crate_is_correct_in_item() {
510 covers!(macro_dollar_crate_self); 547 mark::check!(macro_dollar_crate_self);
511 covers!(macro_dollar_crate_other);
512 let map = def_map( 548 let map = def_map(
513 " 549 "
514 //- /main.rs crate:main deps:foo 550 //- /main.rs crate:main deps:foo
@@ -566,7 +602,7 @@ fn macro_dollar_crate_is_correct_in_item() {
566 602
567#[test] 603#[test]
568fn macro_dollar_crate_is_correct_in_indirect_deps() { 604fn macro_dollar_crate_is_correct_in_indirect_deps() {
569 covers!(macro_dollar_crate_other); 605 mark::check!(macro_dollar_crate_other);
570 // From std 606 // From std
571 let map = def_map( 607 let map = def_map(
572 r#" 608 r#"
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
index 37fcdfb8c..b43b294ca 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
@@ -2,7 +2,7 @@ use super::*;
2 2
3#[test] 3#[test]
4fn name_res_works_for_broken_modules() { 4fn name_res_works_for_broken_modules() {
5 covers!(name_res_works_for_broken_modules); 5 mark::check!(name_res_works_for_broken_modules);
6 let map = def_map( 6 let map = def_map(
7 r" 7 r"
8 //- /lib.rs 8 //- /lib.rs
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index e3d237a0a..6a0c019fd 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -116,6 +116,21 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
116 } 116 }
117 segments.reverse(); 117 segments.reverse();
118 generic_args.reverse(); 118 generic_args.reverse();
119
120 // handle local_inner_macros :
121 // Basically, even in rustc it is quite hacky:
122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
123 // We follow what it did anyway :)
124 if segments.len() == 1 && kind == PathKind::Plain {
125 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
126 if macro_call.is_bang() {
127 if let Some(crate_id) = hygiene.local_inner_macros() {
128 kind = PathKind::DollarCrate(crate_id);
129 }
130 }
131 }
132 }
133
119 let mod_path = ModPath { kind, segments }; 134 let mod_path = ModPath { kind, segments };
120 return Some(Path { type_anchor, mod_path, generic_args }); 135 return Some(Path { type_anchor, mod_path, generic_args });
121 136
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs
index 5b6854b0f..7cc655487 100644
--- a/crates/ra_hir_def/src/path/lower/lower_use.rs
+++ b/crates/ra_hir_def/src/path/lower/lower_use.rs
@@ -6,7 +6,7 @@ use std::iter;
6use either::Either; 6use either::Either;
7use hir_expand::{hygiene::Hygiene, name::AsName}; 7use hir_expand::{hygiene::Hygiene, name::AsName};
8use ra_syntax::ast::{self, NameOwner}; 8use ra_syntax::ast::{self, NameOwner};
9use test_utils::tested_by; 9use test_utils::mark;
10 10
11use crate::path::{ImportAlias, ModPath, PathKind}; 11use crate::path::{ImportAlias, ModPath, PathKind};
12 12
@@ -54,7 +54,7 @@ pub(crate) fn lower_use_tree(
54 // FIXME: report errors somewhere 54 // FIXME: report errors somewhere
55 // We get here if we do 55 // We get here if we do
56 } else if is_glob { 56 } else if is_glob {
57 tested_by!(glob_enum_group); 57 mark::hit!(glob_enum_group);
58 if let Some(prefix) = prefix { 58 if let Some(prefix) = prefix {
59 cb(prefix, &tree, is_glob, None) 59 cb(prefix, &tree, is_glob, None)
60 } 60 }
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 717506358..15fdd9019 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -86,6 +86,7 @@ pub enum ResolveValueResult {
86 86
87#[derive(Debug, Clone, PartialEq, Eq, Hash)] 87#[derive(Debug, Clone, PartialEq, Eq, Hash)]
88pub enum ValueNs { 88pub enum ValueNs {
89 ImplSelf(ImplId),
89 LocalBinding(PatId), 90 LocalBinding(PatId),
90 FunctionId(FunctionId), 91 FunctionId(FunctionId),
91 ConstId(ConstId), 92 ConstId(ConstId),
@@ -291,19 +292,26 @@ impl Resolver {
291 } 292 }
292 Scope::GenericParams { .. } => continue, 293 Scope::GenericParams { .. } => continue,
293 294
294 Scope::ImplDefScope(impl_) if n_segments > 1 => { 295 Scope::ImplDefScope(impl_) => {
295 if first_name == &name![Self] { 296 if first_name == &name![Self] {
296 let ty = TypeNs::SelfType(*impl_); 297 if n_segments > 1 {
297 return Some(ResolveValueResult::Partial(ty, 1)); 298 let ty = TypeNs::SelfType(*impl_);
299 return Some(ResolveValueResult::Partial(ty, 1));
300 } else {
301 return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(*impl_)));
302 }
298 } 303 }
299 } 304 }
300 Scope::AdtScope(adt) if n_segments > 1 => { 305 Scope::AdtScope(adt) => {
306 if n_segments == 1 {
307 // bare `Self` doesn't work in the value namespace in a struct/enum definition
308 continue;
309 }
301 if first_name == &name![Self] { 310 if first_name == &name![Self] {
302 let ty = TypeNs::AdtSelfType(*adt); 311 let ty = TypeNs::AdtSelfType(*adt);
303 return Some(ResolveValueResult::Partial(ty, 1)); 312 return Some(ResolveValueResult::Partial(ty, 1));
304 } 313 }
305 } 314 }
306 Scope::ImplDefScope(_) | Scope::AdtScope(_) => continue,
307 315
308 Scope::ModuleScope(m) => { 316 Scope::ModuleScope(m) => {
309 let (module_def, idx) = m.crate_def_map.resolve_path( 317 let (module_def, idx) = m.crate_def_map.resolve_path(