aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/adt.rs33
-rw-r--r--crates/ra_hir_def/src/attr.rs3
-rw-r--r--crates/ra_hir_def/src/body.rs15
-rw-r--r--crates/ra_hir_def/src/body/lower.rs174
-rw-r--r--crates/ra_hir_def/src/body/scope.rs8
-rw-r--r--crates/ra_hir_def/src/data.rs221
-rw-r--r--crates/ra_hir_def/src/db.rs22
-rw-r--r--crates/ra_hir_def/src/expr.rs26
-rw-r--r--crates/ra_hir_def/src/find_path.rs105
-rw-r--r--crates/ra_hir_def/src/generics.rs68
-rw-r--r--crates/ra_hir_def/src/item_scope.rs11
-rw-r--r--crates/ra_hir_def/src/lang_item.rs14
-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.rs53
-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.rs5
-rw-r--r--crates/ra_hir_def/src/path/lower.rs38
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs4
-rw-r--r--crates/ra_hir_def/src/resolver.rs18
-rw-r--r--crates/ra_hir_def/src/type_ref.rs68
26 files changed, 662 insertions, 369 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 753becc3d..2bc34d449 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -12,9 +12,15 @@ use ra_prof::profile;
12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
13 13
14use crate::{ 14use crate::{
15 body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, 15 body::{CfgExpander, LowerCtx},
16 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, 16 db::DefDatabase,
17 LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, 17 src::HasChildSource,
18 src::HasSource,
19 trace::Trace,
20 type_ref::TypeRef,
21 visibility::RawVisibility,
22 EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId,
23 VariantId,
18}; 24};
19 25
20/// Note that we use `StructData` for unions as well! 26/// Note that we use `StructData` for unions as well!
@@ -111,7 +117,14 @@ fn lower_enum(
111 ast: &InFile<ast::EnumDef>, 117 ast: &InFile<ast::EnumDef>,
112 module_id: ModuleId, 118 module_id: ModuleId,
113) { 119) {
114 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 {
115 trace.alloc( 128 trace.alloc(
116 || var.clone(), 129 || var.clone(),
117 || EnumVariantData { 130 || EnumVariantData {
@@ -198,11 +211,12 @@ fn lower_struct(
198 trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, 211 trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
199 ast: &InFile<ast::StructKind>, 212 ast: &InFile<ast::StructKind>,
200) -> StructKind { 213) -> StructKind {
214 let ctx = LowerCtx::new(db, ast.file_id);
215
201 match &ast.value { 216 match &ast.value {
202 ast::StructKind::Tuple(fl) => { 217 ast::StructKind::Tuple(fl) => {
203 for (i, fd) in fl.fields().enumerate() { 218 for (i, fd) in fl.fields().enumerate() {
204 let attrs = expander.parse_attrs(&fd); 219 if !expander.is_cfg_enabled(&fd) {
205 if !expander.is_cfg_enabled(&attrs) {
206 continue; 220 continue;
207 } 221 }
208 222
@@ -210,7 +224,7 @@ fn lower_struct(
210 || Either::Left(fd.clone()), 224 || Either::Left(fd.clone()),
211 || FieldData { 225 || FieldData {
212 name: Name::new_tuple_field(i), 226 name: Name::new_tuple_field(i),
213 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 227 type_ref: TypeRef::from_ast_opt(&ctx, fd.type_ref()),
214 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 228 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
215 }, 229 },
216 ); 230 );
@@ -219,8 +233,7 @@ fn lower_struct(
219 } 233 }
220 ast::StructKind::Record(fl) => { 234 ast::StructKind::Record(fl) => {
221 for fd in fl.fields() { 235 for fd in fl.fields() {
222 let attrs = expander.parse_attrs(&fd); 236 if !expander.is_cfg_enabled(&fd) {
223 if !expander.is_cfg_enabled(&attrs) {
224 continue; 237 continue;
225 } 238 }
226 239
@@ -228,7 +241,7 @@ fn lower_struct(
228 || Either::Right(fd.clone()), 241 || Either::Right(fd.clone()),
229 || FieldData { 242 || FieldData {
230 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 243 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
231 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 244 type_ref: TypeRef::from_ast_opt(&ctx, fd.ascribed_type()),
232 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 245 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
233 }, 246 },
234 ); 247 );
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 5a86af8ba..8b6c0bede 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -81,7 +81,7 @@ impl Attrs {
81 } 81 }
82 } 82 }
83 83
84 fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { 84 pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
85 let hygiene = Hygiene::new(db.upcast(), owner.file_id); 85 let hygiene = Hygiene::new(db.upcast(), owner.file_id);
86 Attrs::new(owner.value, &hygiene) 86 Attrs::new(owner.value, &hygiene)
87 } 87 }
@@ -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 890cefcaf..273036cee 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -15,6 +15,8 @@ use ra_prof::profile;
15use ra_syntax::{ast, AstNode, AstPtr}; 15use ra_syntax::{ast, AstNode, AstPtr};
16use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
17 17
18pub(crate) use lower::LowerCtx;
19
18use crate::{ 20use crate::{
19 attr::Attrs, 21 attr::Attrs,
20 db::DefDatabase, 22 db::DefDatabase,
@@ -27,7 +29,7 @@ use crate::{
27 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, 29 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
28}; 30};
29 31
30/// A subset of Exander that only deals with cfg attributes. We only need it to 32/// A subset of Expander that only deals with cfg attributes. We only need it to
31/// avoid cyclic queries in crate def map during enum processing. 33/// avoid cyclic queries in crate def map during enum processing.
32pub(crate) struct CfgExpander { 34pub(crate) struct CfgExpander {
33 cfg_options: CfgOptions, 35 cfg_options: CfgOptions,
@@ -58,7 +60,8 @@ impl CfgExpander {
58 Attrs::new(owner, &self.hygiene) 60 Attrs::new(owner, &self.hygiene)
59 } 61 }
60 62
61 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);
62 attrs.is_cfg_enabled(&self.cfg_options) 65 attrs.is_cfg_enabled(&self.cfg_options)
63 } 66 }
64} 67}
@@ -139,12 +142,8 @@ impl Expander {
139 InFile { file_id: self.current_file_id, value } 142 InFile { file_id: self.current_file_id, value }
140 } 143 }
141 144
142 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { 145 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
143 self.cfg_expander.parse_attrs(owner) 146 self.cfg_expander.is_cfg_enabled(owner)
144 }
145
146 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
147 self.cfg_expander.is_cfg_enabled(attrs)
148 } 147 }
149 148
150 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 f467ed3fe..f159f80af 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -3,8 +3,9 @@
3 3
4use either::Either; 4use either::Either;
5use hir_expand::{ 5use hir_expand::{
6 hygiene::Hygiene,
6 name::{name, AsName, Name}, 7 name::{name, AsName, Name},
7 MacroDefId, MacroDefKind, 8 HirFileId, MacroDefId, MacroDefKind,
8}; 9};
9use ra_arena::Arena; 10use ra_arena::Arena;
10use ra_syntax::{ 11use ra_syntax::{
@@ -14,7 +15,7 @@ use ra_syntax::{
14 }, 15 },
15 AstNode, AstPtr, 16 AstNode, AstPtr,
16}; 17};
17use test_utils::tested_by; 18use test_utils::mark;
18 19
19use crate::{ 20use crate::{
20 adt::StructKind, 21 adt::StructKind,
@@ -26,8 +27,8 @@ use crate::{
26 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
27 }, 28 },
28 item_scope::BuiltinShadowMode, 29 item_scope::BuiltinShadowMode,
29 path::GenericArgs, 30 path::{GenericArgs, Path},
30 type_ref::{Mutability, TypeRef}, 31 type_ref::{Mutability, Rawness, TypeRef},
31 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, 32 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
32 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 33 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
33}; 34};
@@ -35,6 +36,23 @@ use crate::{
35use super::{ExprSource, PatSource}; 36use super::{ExprSource, PatSource};
36use ast::AstChildren; 37use ast::AstChildren;
37 38
39pub(crate) struct LowerCtx {
40 hygiene: Hygiene,
41}
42
43impl LowerCtx {
44 pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self {
45 LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) }
46 }
47 pub fn with_hygiene(hygiene: &Hygiene) -> Self {
48 LowerCtx { hygiene: hygiene.clone() }
49 }
50
51 pub fn lower_path(&self, ast: ast::Path) -> Option<Path> {
52 Path::from_src(ast, &self.hygiene)
53 }
54}
55
38pub(super) fn lower( 56pub(super) fn lower(
39 db: &dyn DefDatabase, 57 db: &dyn DefDatabase,
40 def: DefWithBodyId, 58 def: DefWithBodyId,
@@ -62,7 +80,6 @@ struct ExprCollector<'a> {
62 db: &'a dyn DefDatabase, 80 db: &'a dyn DefDatabase,
63 def: DefWithBodyId, 81 def: DefWithBodyId,
64 expander: Expander, 82 expander: Expander,
65
66 body: Body, 83 body: Body,
67 source_map: BodySourceMap, 84 source_map: BodySourceMap,
68} 85}
@@ -101,6 +118,10 @@ impl ExprCollector<'_> {
101 (self.body, self.source_map) 118 (self.body, self.source_map)
102 } 119 }
103 120
121 fn ctx(&self) -> LowerCtx {
122 LowerCtx::new(self.db, self.expander.current_file_id)
123 }
124
104 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 {
105 let src = self.expander.to_source(ptr); 126 let src = self.expander.to_source(ptr);
106 let id = self.make_expr(expr, Ok(src.clone())); 127 let id = self.make_expr(expr, Ok(src.clone()));
@@ -113,7 +134,7 @@ impl ExprCollector<'_> {
113 self.make_expr(expr, Err(SyntheticSyntax)) 134 self.make_expr(expr, Err(SyntheticSyntax))
114 } 135 }
115 fn empty_block(&mut self) -> ExprId { 136 fn empty_block(&mut self) -> ExprId {
116 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) 137 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None, label: None })
117 } 138 }
118 fn missing_expr(&mut self) -> ExprId { 139 fn missing_expr(&mut self) -> ExprId {
119 self.alloc_expr_desugared(Expr::Missing) 140 self.alloc_expr_desugared(Expr::Missing)
@@ -141,8 +162,7 @@ impl ExprCollector<'_> {
141 162
142 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 163 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
143 let syntax_ptr = AstPtr::new(&expr); 164 let syntax_ptr = AstPtr::new(&expr);
144 let attrs = self.expander.parse_attrs(&expr); 165 if !self.expander.is_cfg_enabled(&expr) {
145 if !self.expander.is_cfg_enabled(&attrs) {
146 return self.missing_expr(); 166 return self.missing_expr();
147 } 167 }
148 match expr { 168 match expr {
@@ -182,10 +202,29 @@ impl ExprCollector<'_> {
182 202
183 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)
184 } 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 },
185 ast::Expr::BlockExpr(e) => self.collect_block(e), 215 ast::Expr::BlockExpr(e) => self.collect_block(e),
186 ast::Expr::LoopExpr(e) => { 216 ast::Expr::LoopExpr(e) => {
187 let body = self.collect_block_opt(e.loop_body()); 217 let body = self.collect_block_opt(e.loop_body());
188 self.alloc_expr(Expr::Loop { body }, syntax_ptr) 218 self.alloc_expr(
219 Expr::Loop {
220 body,
221 label: e
222 .label()
223 .and_then(|l| l.lifetime_token())
224 .map(|l| Name::new_lifetime(&l)),
225 },
226 syntax_ptr,
227 )
189 } 228 }
190 ast::Expr::WhileExpr(e) => { 229 ast::Expr::WhileExpr(e) => {
191 let body = self.collect_block_opt(e.loop_body()); 230 let body = self.collect_block_opt(e.loop_body());
@@ -196,29 +235,60 @@ impl ExprCollector<'_> {
196 None => self.collect_expr_opt(condition.expr()), 235 None => self.collect_expr_opt(condition.expr()),
197 // if let -- desugar to match 236 // if let -- desugar to match
198 Some(pat) => { 237 Some(pat) => {
199 tested_by!(infer_resolve_while_let); 238 mark::hit!(infer_resolve_while_let);
200 let pat = self.collect_pat(pat); 239 let pat = self.collect_pat(pat);
201 let match_expr = self.collect_expr_opt(condition.expr()); 240 let match_expr = self.collect_expr_opt(condition.expr());
202 let placeholder_pat = self.missing_pat(); 241 let placeholder_pat = self.missing_pat();
203 let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); 242 let break_ =
243 self.alloc_expr_desugared(Expr::Break { expr: None, label: None });
204 let arms = vec![ 244 let arms = vec![
205 MatchArm { pat, expr: body, guard: None }, 245 MatchArm { pat, expr: body, guard: None },
206 MatchArm { pat: placeholder_pat, expr: break_, guard: None }, 246 MatchArm { pat: placeholder_pat, expr: break_, guard: None },
207 ]; 247 ];
208 let match_expr = 248 let match_expr =
209 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); 249 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
210 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); 250 return self.alloc_expr(
251 Expr::Loop {
252 body: match_expr,
253 label: e
254 .label()
255 .and_then(|l| l.lifetime_token())
256 .map(|l| Name::new_lifetime(&l)),
257 },
258 syntax_ptr,
259 );
211 } 260 }
212 }, 261 },
213 }; 262 };
214 263
215 self.alloc_expr(Expr::While { condition, body }, syntax_ptr) 264 self.alloc_expr(
265 Expr::While {
266 condition,
267 body,
268 label: e
269 .label()
270 .and_then(|l| l.lifetime_token())
271 .map(|l| Name::new_lifetime(&l)),
272 },
273 syntax_ptr,
274 )
216 } 275 }
217 ast::Expr::ForExpr(e) => { 276 ast::Expr::ForExpr(e) => {
218 let iterable = self.collect_expr_opt(e.iterable()); 277 let iterable = self.collect_expr_opt(e.iterable());
219 let pat = self.collect_pat_opt(e.pat()); 278 let pat = self.collect_pat_opt(e.pat());
220 let body = self.collect_block_opt(e.loop_body()); 279 let body = self.collect_block_opt(e.loop_body());
221 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr) 280 self.alloc_expr(
281 Expr::For {
282 iterable,
283 pat,
284 body,
285 label: e
286 .label()
287 .and_then(|l| l.lifetime_token())
288 .map(|l| Name::new_lifetime(&l)),
289 },
290 syntax_ptr,
291 )
222 } 292 }
223 ast::Expr::CallExpr(e) => { 293 ast::Expr::CallExpr(e) => {
224 let callee = self.collect_expr_opt(e.expr()); 294 let callee = self.collect_expr_opt(e.expr());
@@ -237,7 +307,8 @@ impl ExprCollector<'_> {
237 Vec::new() 307 Vec::new()
238 }; 308 };
239 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 309 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
240 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast); 310 let generic_args =
311 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
241 self.alloc_expr( 312 self.alloc_expr(
242 Expr::MethodCall { receiver, method_name, args, generic_args }, 313 Expr::MethodCall { receiver, method_name, args, generic_args },
243 syntax_ptr, 314 syntax_ptr,
@@ -270,13 +341,16 @@ impl ExprCollector<'_> {
270 .unwrap_or(Expr::Missing); 341 .unwrap_or(Expr::Missing);
271 self.alloc_expr(path, syntax_ptr) 342 self.alloc_expr(path, syntax_ptr)
272 } 343 }
273 ast::Expr::ContinueExpr(_e) => { 344 ast::Expr::ContinueExpr(e) => self.alloc_expr(
274 // FIXME: labels 345 Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
275 self.alloc_expr(Expr::Continue, syntax_ptr) 346 syntax_ptr,
276 } 347 ),
277 ast::Expr::BreakExpr(e) => { 348 ast::Expr::BreakExpr(e) => {
278 let expr = e.expr().map(|e| self.collect_expr(e)); 349 let expr = e.expr().map(|e| self.collect_expr(e));
279 self.alloc_expr(Expr::Break { expr }, syntax_ptr) 350 self.alloc_expr(
351 Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
352 syntax_ptr,
353 )
280 } 354 }
281 ast::Expr::ParenExpr(e) => { 355 ast::Expr::ParenExpr(e) => {
282 let inner = self.collect_expr_opt(e.expr()); 356 let inner = self.collect_expr_opt(e.expr());
@@ -297,8 +371,7 @@ impl ExprCollector<'_> {
297 .fields() 371 .fields()
298 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 372 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
299 .filter_map(|field| { 373 .filter_map(|field| {
300 let attrs = self.expander.parse_attrs(&field); 374 if !self.expander.is_cfg_enabled(&field) {
301 if !self.expander.is_cfg_enabled(&attrs) {
302 return None; 375 return None;
303 } 376 }
304 let name = field.field_name()?.as_name(); 377 let name = field.field_name()?.as_name();
@@ -343,13 +416,26 @@ impl ExprCollector<'_> {
343 } 416 }
344 ast::Expr::CastExpr(e) => { 417 ast::Expr::CastExpr(e) => {
345 let expr = self.collect_expr_opt(e.expr()); 418 let expr = self.collect_expr_opt(e.expr());
346 let type_ref = TypeRef::from_ast_opt(e.type_ref()); 419 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
347 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 420 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
348 } 421 }
349 ast::Expr::RefExpr(e) => { 422 ast::Expr::RefExpr(e) => {
350 let expr = self.collect_expr_opt(e.expr()); 423 let expr = self.collect_expr_opt(e.expr());
351 let mutability = Mutability::from_mutable(e.mut_token().is_some()); 424 let raw_tok = e.raw_token().is_some();
352 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr) 425 let mutability = if raw_tok {
426 if e.mut_token().is_some() {
427 Mutability::Mut
428 } else if e.const_token().is_some() {
429 Mutability::Shared
430 } else {
431 unreachable!("parser only remaps to raw_token() if matching mutability token follows")
432 }
433 } else {
434 Mutability::from_mutable(e.mut_token().is_some())
435 };
436 let rawness = Rawness::from_raw(raw_tok);
437
438 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
353 } 439 }
354 ast::Expr::PrefixExpr(e) => { 440 ast::Expr::PrefixExpr(e) => {
355 let expr = self.collect_expr_opt(e.expr()); 441 let expr = self.collect_expr_opt(e.expr());
@@ -365,12 +451,16 @@ impl ExprCollector<'_> {
365 if let Some(pl) = e.param_list() { 451 if let Some(pl) = e.param_list() {
366 for param in pl.params() { 452 for param in pl.params() {
367 let pat = self.collect_pat_opt(param.pat()); 453 let pat = self.collect_pat_opt(param.pat());
368 let type_ref = param.ascribed_type().map(TypeRef::from_ast); 454 let type_ref =
455 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
369 args.push(pat); 456 args.push(pat);
370 arg_types.push(type_ref); 457 arg_types.push(type_ref);
371 } 458 }
372 } 459 }
373 let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); 460 let ret_type = e
461 .ret_type()
462 .and_then(|r| r.type_ref())
463 .map(|it| TypeRef::from_ast(&self.ctx(), it));
374 let body = self.collect_expr_opt(e.body()); 464 let body = self.collect_expr_opt(e.body());
375 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 465 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
376 } 466 }
@@ -430,6 +520,7 @@ impl ExprCollector<'_> {
430 krate: Some(self.expander.module.krate), 520 krate: Some(self.expander.module.krate),
431 ast_id: Some(self.expander.ast_id(&e)), 521 ast_id: Some(self.expander.ast_id(&e)),
432 kind: MacroDefKind::Declarative, 522 kind: MacroDefKind::Declarative,
523 local_inner: false,
433 }; 524 };
434 self.body.item_scope.define_legacy_macro(name, mac); 525 self.body.item_scope.define_legacy_macro(name, mac);
435 526
@@ -464,19 +555,16 @@ impl ExprCollector<'_> {
464 } 555 }
465 } 556 }
466 557
467 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { 558 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
468 let syntax_node_ptr = AstPtr::new(&expr.clone().into()); 559 let syntax_node_ptr = AstPtr::new(&block.clone().into());
469 let block = match expr.block() {
470 Some(block) => block,
471 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
472 };
473 self.collect_block_items(&block); 560 self.collect_block_items(&block);
474 let statements = block 561 let statements = block
475 .statements() 562 .statements()
476 .map(|s| match s { 563 .map(|s| match s {
477 ast::Stmt::LetStmt(stmt) => { 564 ast::Stmt::LetStmt(stmt) => {
478 let pat = self.collect_pat_opt(stmt.pat()); 565 let pat = self.collect_pat_opt(stmt.pat());
479 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); 566 let type_ref =
567 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
480 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 568 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
481 Statement::Let { pat, type_ref, initializer } 569 Statement::Let { pat, type_ref, initializer }
482 } 570 }
@@ -484,10 +572,11 @@ impl ExprCollector<'_> {
484 }) 572 })
485 .collect(); 573 .collect();
486 let tail = block.expr().map(|e| self.collect_expr(e)); 574 let tail = block.expr().map(|e| self.collect_expr(e));
487 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 575 let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t));
576 self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
488 } 577 }
489 578
490 fn collect_block_items(&mut self, block: &ast::Block) { 579 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
491 let container = ContainerId::DefWithBodyId(self.def); 580 let container = ContainerId::DefWithBodyId(self.def);
492 for item in block.items() { 581 for item in block.items() {
493 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 582 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
@@ -542,9 +631,16 @@ impl ExprCollector<'_> {
542 self.body.item_scope.define_def(def); 631 self.body.item_scope.define_def(def);
543 if let Some(name) = name { 632 if let Some(name) = name {
544 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 633 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
545 self.body 634 let has_constructor = match def {
546 .item_scope 635 ModuleDefId::AdtId(AdtId::StructId(s)) => {
547 .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); 636 self.db.struct_data(s).variant_data.kind() != StructKind::Record
637 }
638 _ => true,
639 };
640 self.body.item_scope.push_res(
641 name.as_name(),
642 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
643 );
548 } 644 }
549 } 645 }
550 } 646 }
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 86f953c80..e48ff38f9 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -138,10 +138,10 @@ fn compute_block_scopes(
138fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { 138fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) {
139 scopes.set_scope(expr, scope); 139 scopes.set_scope(expr, scope);
140 match &body[expr] { 140 match &body[expr] {
141 Expr::Block { statements, tail } => { 141 Expr::Block { statements, tail, .. } => {
142 compute_block_scopes(&statements, *tail, body, scopes, scope); 142 compute_block_scopes(&statements, *tail, body, scopes, scope);
143 } 143 }
144 Expr::For { iterable, pat, body: body_expr } => { 144 Expr::For { iterable, pat, body: body_expr, .. } => {
145 compute_expr_scopes(*iterable, body, scopes, scope); 145 compute_expr_scopes(*iterable, body, scopes, scope);
146 let scope = scopes.new_scope(scope); 146 let scope = scopes.new_scope(scope);
147 scopes.add_bindings(body, scope, *pat); 147 scopes.add_bindings(body, scope, *pat);
@@ -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 ccb682f9a..807195d25 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -9,12 +9,13 @@ 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
16use crate::{ 16use crate::{
17 attr::Attrs, 17 attr::Attrs,
18 body::LowerCtx,
18 db::DefDatabase, 19 db::DefDatabase,
19 path::{path, AssociatedTypeBinding, GenericArgs, Path}, 20 path::{path, AssociatedTypeBinding, GenericArgs, Path},
20 src::HasSource, 21 src::HasSource,
@@ -33,6 +34,7 @@ pub struct FunctionData {
33 /// True if the first param is `self`. This is relevant to decide whether this 34 /// True if the first param is `self`. This is relevant to decide whether this
34 /// can be called as a method. 35 /// can be called as a method.
35 pub has_self_param: bool, 36 pub has_self_param: bool,
37 pub is_unsafe: bool,
36 pub visibility: RawVisibility, 38 pub visibility: RawVisibility,
37} 39}
38 40
@@ -40,13 +42,14 @@ impl FunctionData {
40 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { 42 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
41 let loc = func.lookup(db); 43 let loc = func.lookup(db);
42 let src = loc.source(db); 44 let src = loc.source(db);
45 let ctx = LowerCtx::new(db, src.file_id);
43 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); 46 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
44 let mut params = Vec::new(); 47 let mut params = Vec::new();
45 let mut has_self_param = false; 48 let mut has_self_param = false;
46 if let Some(param_list) = src.value.param_list() { 49 if let Some(param_list) = src.value.param_list() {
47 if let Some(self_param) = param_list.self_param() { 50 if let Some(self_param) = param_list.self_param() {
48 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 51 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
49 TypeRef::from_ast(type_ref) 52 TypeRef::from_ast(&ctx, type_ref)
50 } else { 53 } else {
51 let self_type = TypeRef::Path(name![Self].into()); 54 let self_type = TypeRef::Path(name![Self].into());
52 match self_param.kind() { 55 match self_param.kind() {
@@ -63,14 +66,14 @@ impl FunctionData {
63 has_self_param = true; 66 has_self_param = true;
64 } 67 }
65 for param in param_list.params() { 68 for param in param_list.params() {
66 let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); 69 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
67 params.push(type_ref); 70 params.push(type_ref);
68 } 71 }
69 } 72 }
70 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); 73 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id));
71 74
72 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { 75 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
73 TypeRef::from_ast(type_ref) 76 TypeRef::from_ast(&ctx, type_ref)
74 } else { 77 } else {
75 TypeRef::unit() 78 TypeRef::unit()
76 }; 79 };
@@ -83,11 +86,14 @@ impl FunctionData {
83 ret_type 86 ret_type
84 }; 87 };
85 88
89 let is_unsafe = src.value.unsafe_token().is_some();
90
86 let vis_default = RawVisibility::default_for_container(loc.container); 91 let vis_default = RawVisibility::default_for_container(loc.container);
87 let visibility = 92 let visibility =
88 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); 93 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility()));
89 94
90 let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs }; 95 let sig =
96 FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs };
91 Arc::new(sig) 97 Arc::new(sig)
92 } 98 }
93} 99}
@@ -122,7 +128,8 @@ impl TypeAliasData {
122 let loc = typ.lookup(db); 128 let loc = typ.lookup(db);
123 let node = loc.source(db); 129 let node = loc.source(db);
124 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); 130 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name());
125 let type_ref = node.value.type_ref().map(TypeRef::from_ast); 131 let lower_ctx = LowerCtx::new(db, node.file_id);
132 let type_ref = node.value.type_ref().map(|it| TypeRef::from_ast(&lower_ctx, it));
126 let vis_default = RawVisibility::default_for_container(loc.container); 133 let vis_default = RawVisibility::default_for_container(loc.container);
127 let visibility = RawVisibility::from_ast_with_default( 134 let visibility = RawVisibility::from_ast_with_default(
128 db, 135 db,
@@ -130,7 +137,7 @@ impl TypeAliasData {
130 node.as_ref().map(|n| n.visibility()), 137 node.as_ref().map(|n| n.visibility()),
131 ); 138 );
132 let bounds = if let Some(bound_list) = node.value.type_bound_list() { 139 let bounds = if let Some(bound_list) = node.value.type_bound_list() {
133 bound_list.bounds().map(TypeBound::from_ast).collect() 140 bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect()
134 } else { 141 } else {
135 Vec::new() 142 Vec::new()
136 }; 143 };
@@ -147,51 +154,31 @@ pub struct TraitData {
147 154
148impl TraitData { 155impl TraitData {
149 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 156 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
150 let src = tr.lookup(db).source(db); 157 let tr_loc = tr.lookup(db);
158 let src = tr_loc.source(db);
151 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 159 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
152 let auto = src.value.auto_token().is_some(); 160 let auto = src.value.auto_token().is_some();
153 let ast_id_map = db.ast_id_map(src.file_id); 161 let module_id = tr_loc.container.module(db);
154 162
155 let container = AssocContainerId::TraitId(tr); 163 let container = AssocContainerId::TraitId(tr);
156 let items = if let Some(item_list) = src.value.item_list() { 164 let mut items = Vec::new();
157 item_list 165
158 .impl_items() 166 if let Some(item_list) = src.value.item_list() {
159 .map(|item_node| match item_node { 167 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
160 ast::ImplItem::FnDef(it) => { 168 items.extend(collect_items(
161 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 169 db,
162 let def = FunctionLoc { 170 &mut expander,
163 container, 171 item_list.assoc_items(),
164 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 172 src.file_id,
165 } 173 container,
166 .intern(db) 174 ));
167 .into(); 175 items.extend(collect_items_in_macros(
168 (name, def) 176 db,
169 } 177 &mut expander,
170 ast::ImplItem::ConstDef(it) => { 178 &src.with_value(item_list),
171 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 179 container,
172 let def = ConstLoc { 180 ));
173 container, 181 }
174 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
175 }
176 .intern(db)
177 .into();
178 (name, def)
179 }
180 ast::ImplItem::TypeAliasDef(it) => {
181 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
182 let def = TypeAliasLoc {
183 container,
184 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
185 }
186 .intern(db)
187 .into();
188 (name, def)
189 }
190 })
191 .collect()
192 } else {
193 Vec::new()
194 };
195 Arc::new(TraitData { name, items, auto }) 182 Arc::new(TraitData { name, items, auto })
196 } 183 }
197 184
@@ -223,29 +210,28 @@ impl ImplData {
223 let _p = profile("impl_data_query"); 210 let _p = profile("impl_data_query");
224 let impl_loc = id.lookup(db); 211 let impl_loc = id.lookup(db);
225 let src = impl_loc.source(db); 212 let src = impl_loc.source(db);
213 let lower_ctx = LowerCtx::new(db, src.file_id);
226 214
227 let target_trait = src.value.target_trait().map(TypeRef::from_ast); 215 let target_trait = src.value.target_trait().map(|it| TypeRef::from_ast(&lower_ctx, it));
228 let target_type = TypeRef::from_ast_opt(src.value.target_type()); 216 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
229 let is_negative = src.value.excl_token().is_some(); 217 let is_negative = src.value.excl_token().is_some();
230 let module_id = impl_loc.container.module(db); 218 let module_id = impl_loc.container.module(db);
219 let container = AssocContainerId::ImplId(id);
231 220
232 let mut items = Vec::new(); 221 let mut items: Vec<AssocItemId> = Vec::new();
233 222
234 if let Some(item_list) = src.value.item_list() { 223 if let Some(item_list) = src.value.item_list() {
235 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 224 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
236 items.extend(collect_impl_items( 225 items.extend(
237 db, 226 collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container)
238 &mut expander, 227 .into_iter()
239 item_list.impl_items(), 228 .map(|(_, item)| item),
240 src.file_id, 229 );
241 id, 230 items.extend(
242 )); 231 collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
243 items.extend(collect_impl_items_in_macros( 232 .into_iter()
244 db, 233 .map(|(_, item)| item),
245 &mut expander, 234 );
246 &src.with_value(item_list),
247 id,
248 ));
249 } 235 }
250 236
251 let res = ImplData { target_trait, target_type, items, is_negative }; 237 let res = ImplData { target_trait, target_type, items, is_negative };
@@ -269,67 +255,90 @@ impl ConstData {
269 Arc::new(ConstData::new(db, vis_default, node)) 255 Arc::new(ConstData::new(db, vis_default, node))
270 } 256 }
271 257
272 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<ConstData> {
273 let node = konst.lookup(db).source(db);
274 Arc::new(ConstData::new(db, RawVisibility::private(), node))
275 }
276
277 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>( 258 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(
278 db: &dyn DefDatabase, 259 db: &dyn DefDatabase,
279 vis_default: RawVisibility, 260 vis_default: RawVisibility,
280 node: InFile<N>, 261 node: InFile<N>,
281 ) -> ConstData { 262 ) -> ConstData {
263 let ctx = LowerCtx::new(db, node.file_id);
282 let name = node.value.name().map(|n| n.as_name()); 264 let name = node.value.name().map(|n| n.as_name());
283 let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type()); 265 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
284 let visibility = 266 let visibility =
285 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); 267 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
286 ConstData { name, type_ref, visibility } 268 ConstData { name, type_ref, visibility }
287 } 269 }
288} 270}
289 271
290fn collect_impl_items_in_macros( 272#[derive(Debug, Clone, PartialEq, Eq)]
273pub struct StaticData {
274 pub name: Option<Name>,
275 pub type_ref: TypeRef,
276 pub visibility: RawVisibility,
277 pub mutable: bool,
278}
279
280impl StaticData {
281 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
282 let node = konst.lookup(db).source(db);
283 let ctx = LowerCtx::new(db, node.file_id);
284
285 let name = node.value.name().map(|n| n.as_name());
286 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
287 let mutable = node.value.mut_token().is_some();
288 let visibility = RawVisibility::from_ast_with_default(
289 db,
290 RawVisibility::private(),
291 node.map(|n| n.visibility()),
292 );
293
294 Arc::new(StaticData { name, type_ref, visibility, mutable })
295 }
296}
297
298fn collect_items_in_macros(
291 db: &dyn DefDatabase, 299 db: &dyn DefDatabase,
292 expander: &mut Expander, 300 expander: &mut Expander,
293 impl_def: &InFile<ast::ItemList>, 301 impl_def: &InFile<ast::ItemList>,
294 id: ImplId, 302 container: AssocContainerId,
295) -> Vec<AssocItemId> { 303) -> Vec<(Name, AssocItemId)> {
296 let mut res = Vec::new(); 304 let mut res = Vec::new();
297 305
298 // We set a limit to protect against infinite recursion 306 // We set a limit to protect against infinite recursion
299 let limit = 100; 307 let limit = 100;
300 308
301 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 309 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
302 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) 310 res.extend(collect_items_in_macro(db, expander, m, container, limit))
303 } 311 }
304 312
305 res 313 res
306} 314}
307 315
308fn collect_impl_items_in_macro( 316fn collect_items_in_macro(
309 db: &dyn DefDatabase, 317 db: &dyn DefDatabase,
310 expander: &mut Expander, 318 expander: &mut Expander,
311 m: ast::MacroCall, 319 m: ast::MacroCall,
312 id: ImplId, 320 container: AssocContainerId,
313 limit: usize, 321 limit: usize,
314) -> Vec<AssocItemId> { 322) -> Vec<(Name, AssocItemId)> {
315 if limit == 0 { 323 if limit == 0 {
316 return Vec::new(); 324 return Vec::new();
317 } 325 }
318 326
319 if let Some((mark, items)) = expander.enter_expand(db, None, m) { 327 if let Some((mark, items)) = expander.enter_expand(db, None, m) {
320 let items: InFile<ast::MacroItems> = expander.to_source(items); 328 let items: InFile<ast::MacroItems> = expander.to_source(items);
321 let mut res = collect_impl_items( 329 let mut res = collect_items(
322 db, 330 db,
323 expander, 331 expander,
324 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 332 items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())),
325 items.file_id, 333 items.file_id,
326 id, 334 container,
327 ); 335 );
336
328 // Recursive collect macros 337 // Recursive collect macros
329 // Note that ast::ModuleItem do not include ast::MacroCall 338 // Note that ast::ModuleItem do not include ast::MacroCall
330 // We cannot use ModuleItemOwner::items here 339 // We cannot use ModuleItemOwner::items here
331 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { 340 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
332 res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) 341 res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
333 } 342 }
334 expander.exit(db, mark); 343 expander.exit(db, mark);
335 res 344 res
@@ -338,44 +347,38 @@ fn collect_impl_items_in_macro(
338 } 347 }
339} 348}
340 349
341fn collect_impl_items( 350fn collect_items(
342 db: &dyn DefDatabase, 351 db: &dyn DefDatabase,
343 expander: &mut Expander, 352 expander: &mut Expander,
344 impl_items: impl Iterator<Item = ImplItem>, 353 assoc_items: impl Iterator<Item = AssocItem>,
345 file_id: crate::HirFileId, 354 file_id: crate::HirFileId,
346 id: ImplId, 355 container: AssocContainerId,
347) -> Vec<AssocItemId> { 356) -> Vec<(Name, AssocItemId)> {
348 let items = db.ast_id_map(file_id); 357 let items = db.ast_id_map(file_id);
349 358
350 impl_items 359 assoc_items
351 .filter_map(|item_node| match item_node { 360 .filter_map(|item_node| match item_node {
352 ast::ImplItem::FnDef(it) => { 361 ast::AssocItem::FnDef(it) => {
353 let attrs = expander.parse_attrs(&it); 362 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
354 if !expander.is_cfg_enabled(&attrs) { 363 if !expander.is_cfg_enabled(&it) {
355 return None; 364 return None;
356 } 365 }
357 let def = FunctionLoc { 366 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
358 container: AssocContainerId::ImplId(id), 367 .intern(db);
359 ast_id: AstId::new(file_id, items.ast_id(&it)), 368 Some((name, def.into()))
360 }
361 .intern(db);
362 Some(def.into())
363 } 369 }
364 ast::ImplItem::ConstDef(it) => { 370 ast::AssocItem::ConstDef(it) => {
365 let def = ConstLoc { 371 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
366 container: AssocContainerId::ImplId(id), 372 let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
367 ast_id: AstId::new(file_id, items.ast_id(&it)), 373 .intern(db);
368 } 374 Some((name, def.into()))
369 .intern(db);
370 Some(def.into())
371 } 375 }
372 ast::ImplItem::TypeAliasDef(it) => { 376 ast::AssocItem::TypeAliasDef(it) => {
373 let def = TypeAliasLoc { 377 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
374 container: AssocContainerId::ImplId(id), 378 let def =
375 ast_id: AstId::new(file_id, items.ast_id(&it)), 379 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
376 } 380 .intern(db);
377 .intern(db); 381 Some((name, def.into()))
378 Some(def.into())
379 } 382 }
380 }) 383 })
381 .collect() 384 .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..ca49b26d1 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -19,7 +19,7 @@ use ra_syntax::ast::RangeOp;
19use crate::{ 19use crate::{
20 builtin_type::{BuiltinFloat, BuiltinInt}, 20 builtin_type::{BuiltinFloat, BuiltinInt},
21 path::{GenericArgs, Path}, 21 path::{GenericArgs, Path},
22 type_ref::{Mutability, TypeRef}, 22 type_ref::{Mutability, Rawness, TypeRef},
23}; 23};
24 24
25pub type ExprId = Idx<Expr>; 25pub type ExprId = Idx<Expr>;
@@ -52,18 +52,22 @@ pub enum Expr {
52 Block { 52 Block {
53 statements: Vec<Statement>, 53 statements: Vec<Statement>,
54 tail: Option<ExprId>, 54 tail: Option<ExprId>,
55 label: Option<Name>,
55 }, 56 },
56 Loop { 57 Loop {
57 body: ExprId, 58 body: ExprId,
59 label: Option<Name>,
58 }, 60 },
59 While { 61 While {
60 condition: ExprId, 62 condition: ExprId,
61 body: ExprId, 63 body: ExprId,
64 label: Option<Name>,
62 }, 65 },
63 For { 66 For {
64 iterable: ExprId, 67 iterable: ExprId,
65 pat: PatId, 68 pat: PatId,
66 body: ExprId, 69 body: ExprId,
70 label: Option<Name>,
67 }, 71 },
68 Call { 72 Call {
69 callee: ExprId, 73 callee: ExprId,
@@ -79,9 +83,12 @@ pub enum Expr {
79 expr: ExprId, 83 expr: ExprId,
80 arms: Vec<MatchArm>, 84 arms: Vec<MatchArm>,
81 }, 85 },
82 Continue, 86 Continue {
87 label: Option<Name>,
88 },
83 Break { 89 Break {
84 expr: Option<ExprId>, 90 expr: Option<ExprId>,
91 label: Option<Name>,
85 }, 92 },
86 Return { 93 Return {
87 expr: Option<ExprId>, 94 expr: Option<ExprId>,
@@ -101,12 +108,16 @@ pub enum Expr {
101 Try { 108 Try {
102 expr: ExprId, 109 expr: ExprId,
103 }, 110 },
111 TryBlock {
112 body: ExprId,
113 },
104 Cast { 114 Cast {
105 expr: ExprId, 115 expr: ExprId,
106 type_ref: TypeRef, 116 type_ref: TypeRef,
107 }, 117 },
108 Ref { 118 Ref {
109 expr: ExprId, 119 expr: ExprId,
120 rawness: Rawness,
110 mutability: Mutability, 121 mutability: Mutability,
111 }, 122 },
112 Box { 123 Box {
@@ -221,7 +232,7 @@ impl Expr {
221 f(*else_branch); 232 f(*else_branch);
222 } 233 }
223 } 234 }
224 Expr::Block { statements, tail } => { 235 Expr::Block { statements, tail, .. } => {
225 for stmt in statements { 236 for stmt in statements {
226 match stmt { 237 match stmt {
227 Statement::Let { initializer, .. } => { 238 Statement::Let { initializer, .. } => {
@@ -236,8 +247,9 @@ impl Expr {
236 f(*expr); 247 f(*expr);
237 } 248 }
238 } 249 }
239 Expr::Loop { body } => f(*body), 250 Expr::TryBlock { body } => f(*body),
240 Expr::While { condition, body } => { 251 Expr::Loop { body, .. } => f(*body),
252 Expr::While { condition, body, .. } => {
241 f(*condition); 253 f(*condition);
242 f(*body); 254 f(*body);
243 } 255 }
@@ -263,8 +275,8 @@ impl Expr {
263 f(arm.expr); 275 f(arm.expr);
264 } 276 }
265 } 277 }
266 Expr::Continue => {} 278 Expr::Continue { .. } => {}
267 Expr::Break { expr } | Expr::Return { expr } => { 279 Expr::Break { expr, .. } | Expr::Return { expr } => {
268 if let Some(expr) = expr { 280 if let Some(expr) = expr {
269 f(*expr); 281 f(*expr);
270 } 282 }
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/generics.rs b/crates/ra_hir_def/src/generics.rs
index d850244c4..09a5241f7 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -15,6 +15,7 @@ use ra_prof::profile;
15use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 15use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
16 16
17use crate::{ 17use crate::{
18 body::LowerCtx,
18 child_by_source::ChildBySource, 19 child_by_source::ChildBySource,
19 db::DefDatabase, 20 db::DefDatabase,
20 dyn_map::DynMap, 21 dyn_map::DynMap,
@@ -80,11 +81,13 @@ impl GenericParams {
80 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { 81 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
81 let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; 82 let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() };
82 let mut sm = ArenaMap::default(); 83 let mut sm = ArenaMap::default();
84
83 // FIXME: add `: Sized` bound for everything except for `Self` in traits 85 // FIXME: add `: Sized` bound for everything except for `Self` in traits
84 let file_id = match def { 86 let file_id = match def {
85 GenericDefId::FunctionId(it) => { 87 GenericDefId::FunctionId(it) => {
86 let src = it.lookup(db).source(db); 88 let src = it.lookup(db).source(db);
87 generics.fill(&mut sm, &src.value); 89 let lower_ctx = LowerCtx::new(db, src.file_id);
90 generics.fill(&lower_ctx, &mut sm, &src.value);
88 // lower `impl Trait` in arguments 91 // lower `impl Trait` in arguments
89 let data = db.function_data(it); 92 let data = db.function_data(it);
90 for param in &data.params { 93 for param in &data.params {
@@ -94,21 +97,25 @@ impl GenericParams {
94 } 97 }
95 GenericDefId::AdtId(AdtId::StructId(it)) => { 98 GenericDefId::AdtId(AdtId::StructId(it)) => {
96 let src = it.lookup(db).source(db); 99 let src = it.lookup(db).source(db);
97 generics.fill(&mut sm, &src.value); 100 let lower_ctx = LowerCtx::new(db, src.file_id);
101 generics.fill(&lower_ctx, &mut sm, &src.value);
98 src.file_id 102 src.file_id
99 } 103 }
100 GenericDefId::AdtId(AdtId::UnionId(it)) => { 104 GenericDefId::AdtId(AdtId::UnionId(it)) => {
101 let src = it.lookup(db).source(db); 105 let src = it.lookup(db).source(db);
102 generics.fill(&mut sm, &src.value); 106 let lower_ctx = LowerCtx::new(db, src.file_id);
107 generics.fill(&lower_ctx, &mut sm, &src.value);
103 src.file_id 108 src.file_id
104 } 109 }
105 GenericDefId::AdtId(AdtId::EnumId(it)) => { 110 GenericDefId::AdtId(AdtId::EnumId(it)) => {
106 let src = it.lookup(db).source(db); 111 let src = it.lookup(db).source(db);
107 generics.fill(&mut sm, &src.value); 112 let lower_ctx = LowerCtx::new(db, src.file_id);
113 generics.fill(&lower_ctx, &mut sm, &src.value);
108 src.file_id 114 src.file_id
109 } 115 }
110 GenericDefId::TraitId(it) => { 116 GenericDefId::TraitId(it) => {
111 let src = it.lookup(db).source(db); 117 let src = it.lookup(db).source(db);
118 let lower_ctx = LowerCtx::new(db, src.file_id);
112 119
113 // traits get the Self type as an implicit first type parameter 120 // traits get the Self type as an implicit first type parameter
114 let self_param_id = generics.types.alloc(TypeParamData { 121 let self_param_id = generics.types.alloc(TypeParamData {
@@ -120,14 +127,16 @@ impl GenericParams {
120 // add super traits as bounds on Self 127 // add super traits as bounds on Self
121 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 128 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
122 let self_param = TypeRef::Path(name![Self].into()); 129 let self_param = TypeRef::Path(name![Self].into());
123 generics.fill_bounds(&src.value, self_param); 130 generics.fill_bounds(&lower_ctx, &src.value, self_param);
124 131
125 generics.fill(&mut sm, &src.value); 132 generics.fill(&lower_ctx, &mut sm, &src.value);
126 src.file_id 133 src.file_id
127 } 134 }
128 GenericDefId::TypeAliasId(it) => { 135 GenericDefId::TypeAliasId(it) => {
129 let src = it.lookup(db).source(db); 136 let src = it.lookup(db).source(db);
130 generics.fill(&mut sm, &src.value); 137 let lower_ctx = LowerCtx::new(db, src.file_id);
138
139 generics.fill(&lower_ctx, &mut sm, &src.value);
131 src.file_id 140 src.file_id
132 } 141 }
133 // Note that we don't add `Self` here: in `impl`s, `Self` is not a 142 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
@@ -135,7 +144,9 @@ impl GenericParams {
135 // type, so this is handled by the resolver. 144 // type, so this is handled by the resolver.
136 GenericDefId::ImplId(it) => { 145 GenericDefId::ImplId(it) => {
137 let src = it.lookup(db).source(db); 146 let src = it.lookup(db).source(db);
138 generics.fill(&mut sm, &src.value); 147 let lower_ctx = LowerCtx::new(db, src.file_id);
148
149 generics.fill(&lower_ctx, &mut sm, &src.value);
139 src.file_id 150 src.file_id
140 } 151 }
141 // We won't be using this ID anyway 152 // We won't be using this ID anyway
@@ -145,28 +156,38 @@ impl GenericParams {
145 (generics, InFile::new(file_id, sm)) 156 (generics, InFile::new(file_id, sm))
146 } 157 }
147 158
148 fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { 159 fn fill(&mut self, lower_ctx: &LowerCtx, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
149 if let Some(params) = node.type_param_list() { 160 if let Some(params) = node.type_param_list() {
150 self.fill_params(sm, params) 161 self.fill_params(lower_ctx, sm, params)
151 } 162 }
152 if let Some(where_clause) = node.where_clause() { 163 if let Some(where_clause) = node.where_clause() {
153 self.fill_where_predicates(where_clause); 164 self.fill_where_predicates(lower_ctx, where_clause);
154 } 165 }
155 } 166 }
156 167
157 fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) { 168 fn fill_bounds(
169 &mut self,
170 lower_ctx: &LowerCtx,
171 node: &dyn ast::TypeBoundsOwner,
172 type_ref: TypeRef,
173 ) {
158 for bound in 174 for bound in
159 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) 175 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
160 { 176 {
161 self.add_where_predicate_from_bound(bound, type_ref.clone()); 177 self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone());
162 } 178 }
163 } 179 }
164 180
165 fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) { 181 fn fill_params(
182 &mut self,
183 lower_ctx: &LowerCtx,
184 sm: &mut SourceMap,
185 params: ast::TypeParamList,
186 ) {
166 for type_param in params.type_params() { 187 for type_param in params.type_params() {
167 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 188 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
168 // FIXME: Use `Path::from_src` 189 // FIXME: Use `Path::from_src`
169 let default = type_param.default_type().map(TypeRef::from_ast); 190 let default = type_param.default_type().map(|it| TypeRef::from_ast(lower_ctx, it));
170 let param = TypeParamData { 191 let param = TypeParamData {
171 name: Some(name.clone()), 192 name: Some(name.clone()),
172 default, 193 default,
@@ -176,29 +197,34 @@ impl GenericParams {
176 sm.insert(param_id, Either::Right(type_param.clone())); 197 sm.insert(param_id, Either::Right(type_param.clone()));
177 198
178 let type_ref = TypeRef::Path(name.into()); 199 let type_ref = TypeRef::Path(name.into());
179 self.fill_bounds(&type_param, type_ref); 200 self.fill_bounds(&lower_ctx, &type_param, type_ref);
180 } 201 }
181 } 202 }
182 203
183 fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) { 204 fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) {
184 for pred in where_clause.predicates() { 205 for pred in where_clause.predicates() {
185 let type_ref = match pred.type_ref() { 206 let type_ref = match pred.type_ref() {
186 Some(type_ref) => type_ref, 207 Some(type_ref) => type_ref,
187 None => continue, 208 None => continue,
188 }; 209 };
189 let type_ref = TypeRef::from_ast(type_ref); 210 let type_ref = TypeRef::from_ast(lower_ctx, type_ref);
190 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { 211 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
191 self.add_where_predicate_from_bound(bound, type_ref.clone()); 212 self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone());
192 } 213 }
193 } 214 }
194 } 215 }
195 216
196 fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) { 217 fn add_where_predicate_from_bound(
218 &mut self,
219 lower_ctx: &LowerCtx,
220 bound: ast::TypeBound,
221 type_ref: TypeRef,
222 ) {
197 if bound.question_token().is_some() { 223 if bound.question_token().is_some() {
198 // FIXME: remove this bound 224 // FIXME: remove this bound
199 return; 225 return;
200 } 226 }
201 let bound = TypeBound::from_ast(bound); 227 let bound = TypeBound::from_ast(lower_ctx, bound);
202 self.where_predicates 228 self.where_predicates
203 .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); 229 .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound });
204 } 230 }
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/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index d96ac8c0a..3516784b8 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -73,8 +73,8 @@ pub struct LangItems {
73} 73}
74 74
75impl LangItems { 75impl LangItems {
76 pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> { 76 pub fn target(&self, item: &str) -> Option<LangItemTarget> {
77 self.items.get(item) 77 self.items.get(item).copied()
78 } 78 }
79 79
80 /// Salsa query. This will look for lang items in a specific crate. 80 /// Salsa query. This will look for lang items in a specific crate.
@@ -163,9 +163,13 @@ impl LangItems {
163 ) where 163 ) where
164 T: Into<AttrDefId> + Copy, 164 T: Into<AttrDefId> + Copy,
165 { 165 {
166 let attrs = db.attrs(item.into()); 166 if let Some(lang_item_name) = lang_attr(db, item) {
167 if let Some(lang_item_name) = attrs.by_key("lang").string_value() { 167 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
168 self.items.entry(lang_item_name.clone()).or_insert_with(|| constructor(item));
169 } 168 }
170 } 169 }
171} 170}
171
172pub fn lang_attr(db: &dyn DefDatabase, item: impl Into<AttrDefId> + Copy) -> Option<SmolStr> {
173 let attrs = db.attrs(item.into());
174 attrs.by_key("lang").string_value().cloned()
175}
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..f44baa579 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>),
@@ -168,10 +175,10 @@ pub(super) enum DefKind {
168} 175}
169 176
170impl DefKind { 177impl 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.rs b/crates/ra_hir_def/src/path.rs
index 162b3c8c7..e84efe2ab 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -7,6 +7,7 @@ use std::{
7 sync::Arc, 7 sync::Arc,
8}; 8};
9 9
10use crate::body::LowerCtx;
10use hir_expand::{ 11use hir_expand::{
11 hygiene::Hygiene, 12 hygiene::Hygiene,
12 name::{AsName, Name}, 13 name::{AsName, Name},
@@ -244,8 +245,8 @@ impl<'a> PathSegments<'a> {
244} 245}
245 246
246impl GenericArgs { 247impl GenericArgs {
247 pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> { 248 pub(crate) fn from_ast(lower_ctx: &LowerCtx, node: ast::TypeArgList) -> Option<GenericArgs> {
248 lower::lower_generic_args(node) 249 lower::lower_generic_args(lower_ctx, node)
249 } 250 }
250 251
251 pub(crate) fn empty() -> GenericArgs { 252 pub(crate) fn empty() -> GenericArgs {
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index 9ec2e0dcd..6a0c019fd 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -13,6 +13,7 @@ use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner};
13 13
14use super::AssociatedTypeBinding; 14use super::AssociatedTypeBinding;
15use crate::{ 15use crate::{
16 body::LowerCtx,
16 path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, 17 path::{GenericArg, GenericArgs, ModPath, Path, PathKind},
17 type_ref::{TypeBound, TypeRef}, 18 type_ref::{TypeBound, TypeRef},
18}; 19};
@@ -26,6 +27,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
26 let mut type_anchor = None; 27 let mut type_anchor = None;
27 let mut segments = Vec::new(); 28 let mut segments = Vec::new();
28 let mut generic_args = Vec::new(); 29 let mut generic_args = Vec::new();
30 let ctx = LowerCtx::with_hygiene(hygiene);
29 loop { 31 loop {
30 let segment = path.segment()?; 32 let segment = path.segment()?;
31 33
@@ -40,9 +42,10 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
40 Either::Left(name) => { 42 Either::Left(name) => {
41 let args = segment 43 let args = segment
42 .type_arg_list() 44 .type_arg_list()
43 .and_then(lower_generic_args) 45 .and_then(|it| lower_generic_args(&ctx, it))
44 .or_else(|| { 46 .or_else(|| {
45 lower_generic_args_from_fn_path( 47 lower_generic_args_from_fn_path(
48 &ctx,
46 segment.param_list(), 49 segment.param_list(),
47 segment.ret_type(), 50 segment.ret_type(),
48 ) 51 )
@@ -60,7 +63,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
60 ast::PathSegmentKind::Type { type_ref, trait_ref } => { 63 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
61 assert!(path.qualifier().is_none()); // this can only occur at the first segment 64 assert!(path.qualifier().is_none()); // this can only occur at the first segment
62 65
63 let self_type = TypeRef::from_ast(type_ref?); 66 let self_type = TypeRef::from_ast(&ctx, type_ref?);
64 67
65 match trait_ref { 68 match trait_ref {
66 // <T>::foo 69 // <T>::foo
@@ -113,6 +116,21 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
113 } 116 }
114 segments.reverse(); 117 segments.reverse();
115 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
116 let mod_path = ModPath { kind, segments }; 134 let mod_path = ModPath { kind, segments };
117 return Some(Path { type_anchor, mod_path, generic_args }); 135 return Some(Path { type_anchor, mod_path, generic_args });
118 136
@@ -128,10 +146,13 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
128 } 146 }
129} 147}
130 148
131pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> { 149pub(super) fn lower_generic_args(
150 lower_ctx: &LowerCtx,
151 node: ast::TypeArgList,
152) -> Option<GenericArgs> {
132 let mut args = Vec::new(); 153 let mut args = Vec::new();
133 for type_arg in node.type_args() { 154 for type_arg in node.type_args() {
134 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); 155 let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.type_ref());
135 args.push(GenericArg::Type(type_ref)); 156 args.push(GenericArg::Type(type_ref));
136 } 157 }
137 // lifetimes ignored for now 158 // lifetimes ignored for now
@@ -140,9 +161,9 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
140 let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg; 161 let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg;
141 if let Some(name_ref) = assoc_type_arg.name_ref() { 162 if let Some(name_ref) = assoc_type_arg.name_ref() {
142 let name = name_ref.as_name(); 163 let name = name_ref.as_name();
143 let type_ref = assoc_type_arg.type_ref().map(TypeRef::from_ast); 164 let type_ref = assoc_type_arg.type_ref().map(|it| TypeRef::from_ast(lower_ctx, it));
144 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { 165 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
145 l.bounds().map(TypeBound::from_ast).collect() 166 l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
146 } else { 167 } else {
147 Vec::new() 168 Vec::new()
148 }; 169 };
@@ -159,6 +180,7 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
159/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) 180/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
160/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). 181/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
161fn lower_generic_args_from_fn_path( 182fn lower_generic_args_from_fn_path(
183 ctx: &LowerCtx,
162 params: Option<ast::ParamList>, 184 params: Option<ast::ParamList>,
163 ret_type: Option<ast::RetType>, 185 ret_type: Option<ast::RetType>,
164) -> Option<GenericArgs> { 186) -> Option<GenericArgs> {
@@ -167,14 +189,14 @@ fn lower_generic_args_from_fn_path(
167 if let Some(params) = params { 189 if let Some(params) = params {
168 let mut param_types = Vec::new(); 190 let mut param_types = Vec::new();
169 for param in params.params() { 191 for param in params.params() {
170 let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); 192 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
171 param_types.push(type_ref); 193 param_types.push(type_ref);
172 } 194 }
173 let arg = GenericArg::Type(TypeRef::Tuple(param_types)); 195 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
174 args.push(arg); 196 args.push(arg);
175 } 197 }
176 if let Some(ret_type) = ret_type { 198 if let Some(ret_type) = ret_type {
177 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); 199 let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.type_ref());
178 bindings.push(AssociatedTypeBinding { 200 bindings.push(AssociatedTypeBinding {
179 name: name![Output], 201 name: name![Output],
180 type_ref: Some(type_ref), 202 type_ref: Some(type_ref),
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(
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index f308c6bdf..86a77b704 100644
--- a/crates/ra_hir_def/src/type_ref.rs
+++ b/crates/ra_hir_def/src/type_ref.rs
@@ -3,7 +3,7 @@
3 3
4use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner}; 4use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner};
5 5
6use crate::path::Path; 6use crate::{body::LowerCtx, path::Path};
7 7
8#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 8#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
9pub enum Mutability { 9pub enum Mutability {
@@ -35,6 +35,22 @@ impl Mutability {
35 } 35 }
36} 36}
37 37
38#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
39pub enum Rawness {
40 RawPtr,
41 Ref,
42}
43
44impl Rawness {
45 pub fn from_raw(is_raw: bool) -> Rawness {
46 if is_raw {
47 Rawness::RawPtr
48 } else {
49 Rawness::Ref
50 }
51 }
52}
53
38/// Compare ty::Ty 54/// Compare ty::Ty
39#[derive(Clone, PartialEq, Eq, Hash, Debug)] 55#[derive(Clone, PartialEq, Eq, Hash, Debug)]
40pub enum TypeRef { 56pub enum TypeRef {
@@ -64,30 +80,34 @@ pub enum TypeBound {
64 80
65impl TypeRef { 81impl TypeRef {
66 /// Converts an `ast::TypeRef` to a `hir::TypeRef`. 82 /// Converts an `ast::TypeRef` to a `hir::TypeRef`.
67 pub(crate) fn from_ast(node: ast::TypeRef) -> Self { 83 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeRef) -> Self {
68 match node { 84 match node {
69 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), 85 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
70 ast::TypeRef::TupleType(inner) => { 86 ast::TypeRef::TupleType(inner) => {
71 TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect()) 87 TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect())
72 } 88 }
73 ast::TypeRef::NeverType(..) => TypeRef::Never, 89 ast::TypeRef::NeverType(..) => TypeRef::Never,
74 ast::TypeRef::PathType(inner) => { 90 ast::TypeRef::PathType(inner) => {
75 // FIXME: Use `Path::from_src` 91 // FIXME: Use `Path::from_src`
76 inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error) 92 inner
93 .path()
94 .and_then(|it| ctx.lower_path(it))
95 .map(TypeRef::Path)
96 .unwrap_or(TypeRef::Error)
77 } 97 }
78 ast::TypeRef::PointerType(inner) => { 98 ast::TypeRef::PointerType(inner) => {
79 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 99 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
80 let mutability = Mutability::from_mutable(inner.mut_token().is_some()); 100 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
81 TypeRef::RawPtr(Box::new(inner_ty), mutability) 101 TypeRef::RawPtr(Box::new(inner_ty), mutability)
82 } 102 }
83 ast::TypeRef::ArrayType(inner) => { 103 ast::TypeRef::ArrayType(inner) => {
84 TypeRef::Array(Box::new(TypeRef::from_ast_opt(inner.type_ref()))) 104 TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
85 } 105 }
86 ast::TypeRef::SliceType(inner) => { 106 ast::TypeRef::SliceType(inner) => {
87 TypeRef::Slice(Box::new(TypeRef::from_ast_opt(inner.type_ref()))) 107 TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
88 } 108 }
89 ast::TypeRef::ReferenceType(inner) => { 109 ast::TypeRef::ReferenceType(inner) => {
90 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 110 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
91 let mutability = Mutability::from_mutable(inner.mut_token().is_some()); 111 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
92 TypeRef::Reference(Box::new(inner_ty), mutability) 112 TypeRef::Reference(Box::new(inner_ty), mutability)
93 } 113 }
@@ -96,10 +116,13 @@ impl TypeRef {
96 let ret_ty = inner 116 let ret_ty = inner
97 .ret_type() 117 .ret_type()
98 .and_then(|rt| rt.type_ref()) 118 .and_then(|rt| rt.type_ref())
99 .map(TypeRef::from_ast) 119 .map(|it| TypeRef::from_ast(ctx, it))
100 .unwrap_or_else(|| TypeRef::Tuple(Vec::new())); 120 .unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
101 let mut params = if let Some(pl) = inner.param_list() { 121 let mut params = if let Some(pl) = inner.param_list() {
102 pl.params().map(|p| p.ascribed_type()).map(TypeRef::from_ast_opt).collect() 122 pl.params()
123 .map(|p| p.ascribed_type())
124 .map(|it| TypeRef::from_ast_opt(&ctx, it))
125 .collect()
103 } else { 126 } else {
104 Vec::new() 127 Vec::new()
105 }; 128 };
@@ -107,19 +130,19 @@ impl TypeRef {
107 TypeRef::Fn(params) 130 TypeRef::Fn(params)
108 } 131 }
109 // for types are close enough for our purposes to the inner type for now... 132 // for types are close enough for our purposes to the inner type for now...
110 ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()), 133 ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
111 ast::TypeRef::ImplTraitType(inner) => { 134 ast::TypeRef::ImplTraitType(inner) => {
112 TypeRef::ImplTrait(type_bounds_from_ast(inner.type_bound_list())) 135 TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
113 } 136 }
114 ast::TypeRef::DynTraitType(inner) => { 137 ast::TypeRef::DynTraitType(inner) => {
115 TypeRef::DynTrait(type_bounds_from_ast(inner.type_bound_list())) 138 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
116 } 139 }
117 } 140 }
118 } 141 }
119 142
120 pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { 143 pub(crate) fn from_ast_opt(ctx: &LowerCtx, node: Option<ast::TypeRef>) -> Self {
121 if let Some(node) = node { 144 if let Some(node) = node {
122 TypeRef::from_ast(node) 145 TypeRef::from_ast(ctx, node)
123 } else { 146 } else {
124 TypeRef::Error 147 TypeRef::Error
125 } 148 }
@@ -180,24 +203,27 @@ impl TypeRef {
180 } 203 }
181} 204}
182 205
183pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { 206pub(crate) fn type_bounds_from_ast(
207 lower_ctx: &LowerCtx,
208 type_bounds_opt: Option<ast::TypeBoundList>,
209) -> Vec<TypeBound> {
184 if let Some(type_bounds) = type_bounds_opt { 210 if let Some(type_bounds) = type_bounds_opt {
185 type_bounds.bounds().map(TypeBound::from_ast).collect() 211 type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
186 } else { 212 } else {
187 vec![] 213 vec![]
188 } 214 }
189} 215}
190 216
191impl TypeBound { 217impl TypeBound {
192 pub(crate) fn from_ast(node: ast::TypeBound) -> Self { 218 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeBound) -> Self {
193 match node.kind() { 219 match node.kind() {
194 ast::TypeBoundKind::PathType(path_type) => { 220 ast::TypeBoundKind::PathType(path_type) => {
195 let path = match path_type.path() { 221 let path = match path_type.path() {
196 Some(p) => p, 222 Some(p) => p,
197 None => return TypeBound::Error, 223 None => return TypeBound::Error,
198 }; 224 };
199 // FIXME: Use `Path::from_src` 225
200 let path = match Path::from_ast(path) { 226 let path = match ctx.lower_path(path) {
201 Some(p) => p, 227 Some(p) => p,
202 None => return TypeBound::Error, 228 None => return TypeBound::Error,
203 }; 229 };