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.rs1
-rw-r--r--crates/ra_hir_def/src/body.rs15
-rw-r--r--crates/ra_hir_def/src/body/lower.rs86
-rw-r--r--crates/ra_hir_def/src/data.rs184
-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/nameres/collector.rs15
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs47
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs2
-rw-r--r--crates/ra_hir_def/src/nameres/tests/macros.rs61
-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/type_ref.rs52
14 files changed, 395 insertions, 223 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..576cd0c65 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -140,6 +140,7 @@ impl Attr {
140 } 140 }
141} 141}
142 142
143#[derive(Debug, Clone, Copy)]
143pub struct AttrQuery<'a> { 144pub struct AttrQuery<'a> {
144 attrs: &'a Attrs, 145 attrs: &'a Attrs,
145 key: &'static str, 146 key: &'static str,
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 3b169440a..f5a7305dc 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 subser of Exander that only deals with cfg attributes. We only need it to 32/// A subset of Exander 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 0caedd8d8..443b057ab 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::{
@@ -26,7 +27,7 @@ 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, 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,
@@ -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,
@@ -42,10 +60,13 @@ pub(super) fn lower(
42 params: Option<ast::ParamList>, 60 params: Option<ast::ParamList>,
43 body: Option<ast::Expr>, 61 body: Option<ast::Expr>,
44) -> (Body, BodySourceMap) { 62) -> (Body, BodySourceMap) {
63 let ctx = LowerCtx::new(db, expander.current_file_id.clone());
64
45 ExprCollector { 65 ExprCollector {
46 db, 66 db,
47 def, 67 def,
48 expander, 68 expander,
69 ctx,
49 source_map: BodySourceMap::default(), 70 source_map: BodySourceMap::default(),
50 body: Body { 71 body: Body {
51 exprs: Arena::default(), 72 exprs: Arena::default(),
@@ -62,7 +83,7 @@ struct ExprCollector<'a> {
62 db: &'a dyn DefDatabase, 83 db: &'a dyn DefDatabase,
63 def: DefWithBodyId, 84 def: DefWithBodyId,
64 expander: Expander, 85 expander: Expander,
65 86 ctx: LowerCtx,
66 body: Body, 87 body: Body,
67 source_map: BodySourceMap, 88 source_map: BodySourceMap,
68} 89}
@@ -141,6 +162,9 @@ 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);
165 if !self.expander.is_cfg_enabled(&expr) {
166 return self.missing_expr();
167 }
144 match expr { 168 match expr {
145 ast::Expr::IfExpr(e) => { 169 ast::Expr::IfExpr(e) => {
146 let then_branch = self.collect_block_opt(e.then_branch()); 170 let then_branch = self.collect_block_opt(e.then_branch());
@@ -178,10 +202,16 @@ impl ExprCollector<'_> {
178 202
179 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)
180 } 204 }
181 ast::Expr::TryBlockExpr(e) => { 205 ast::Expr::EffectExpr(e) => match e.effect() {
182 let body = self.collect_block_opt(e.body()); 206 ast::Effect::Try(_) => {
183 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) 207 let body = self.collect_block_opt(e.block_expr());
184 } 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());
@@ -237,7 +267,8 @@ impl ExprCollector<'_> {
237 Vec::new() 267 Vec::new()
238 }; 268 };
239 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 269 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
240 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast); 270 let generic_args =
271 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it));
241 self.alloc_expr( 272 self.alloc_expr(
242 Expr::MethodCall { receiver, method_name, args, generic_args }, 273 Expr::MethodCall { receiver, method_name, args, generic_args },
243 syntax_ptr, 274 syntax_ptr,
@@ -297,8 +328,7 @@ impl ExprCollector<'_> {
297 .fields() 328 .fields()
298 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 329 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
299 .filter_map(|field| { 330 .filter_map(|field| {
300 let attrs = self.expander.parse_attrs(&field); 331 if !self.expander.is_cfg_enabled(&field) {
301 if !self.expander.is_cfg_enabled(&attrs) {
302 return None; 332 return None;
303 } 333 }
304 let name = field.field_name()?.as_name(); 334 let name = field.field_name()?.as_name();
@@ -343,7 +373,7 @@ impl ExprCollector<'_> {
343 } 373 }
344 ast::Expr::CastExpr(e) => { 374 ast::Expr::CastExpr(e) => {
345 let expr = self.collect_expr_opt(e.expr()); 375 let expr = self.collect_expr_opt(e.expr());
346 let type_ref = TypeRef::from_ast_opt(e.type_ref()); 376 let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref());
347 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 377 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
348 } 378 }
349 ast::Expr::RefExpr(e) => { 379 ast::Expr::RefExpr(e) => {
@@ -365,12 +395,16 @@ impl ExprCollector<'_> {
365 if let Some(pl) = e.param_list() { 395 if let Some(pl) = e.param_list() {
366 for param in pl.params() { 396 for param in pl.params() {
367 let pat = self.collect_pat_opt(param.pat()); 397 let pat = self.collect_pat_opt(param.pat());
368 let type_ref = param.ascribed_type().map(TypeRef::from_ast); 398 let type_ref =
399 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
369 args.push(pat); 400 args.push(pat);
370 arg_types.push(type_ref); 401 arg_types.push(type_ref);
371 } 402 }
372 } 403 }
373 let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); 404 let ret_type = e
405 .ret_type()
406 .and_then(|r| r.type_ref())
407 .map(|it| TypeRef::from_ast(&self.ctx, it));
374 let body = self.collect_expr_opt(e.body()); 408 let body = self.collect_expr_opt(e.body());
375 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 409 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
376 } 410 }
@@ -430,6 +464,7 @@ impl ExprCollector<'_> {
430 krate: Some(self.expander.module.krate), 464 krate: Some(self.expander.module.krate),
431 ast_id: Some(self.expander.ast_id(&e)), 465 ast_id: Some(self.expander.ast_id(&e)),
432 kind: MacroDefKind::Declarative, 466 kind: MacroDefKind::Declarative,
467 local_inner: false,
433 }; 468 };
434 self.body.item_scope.define_legacy_macro(name, mac); 469 self.body.item_scope.define_legacy_macro(name, mac);
435 470
@@ -464,19 +499,15 @@ impl ExprCollector<'_> {
464 } 499 }
465 } 500 }
466 501
467 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { 502 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
468 let syntax_node_ptr = AstPtr::new(&expr.clone().into()); 503 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); 504 self.collect_block_items(&block);
474 let statements = block 505 let statements = block
475 .statements() 506 .statements()
476 .map(|s| match s { 507 .map(|s| match s {
477 ast::Stmt::LetStmt(stmt) => { 508 ast::Stmt::LetStmt(stmt) => {
478 let pat = self.collect_pat_opt(stmt.pat()); 509 let pat = self.collect_pat_opt(stmt.pat());
479 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); 510 let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
480 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 511 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
481 Statement::Let { pat, type_ref, initializer } 512 Statement::Let { pat, type_ref, initializer }
482 } 513 }
@@ -487,7 +518,7 @@ impl ExprCollector<'_> {
487 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 518 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
488 } 519 }
489 520
490 fn collect_block_items(&mut self, block: &ast::Block) { 521 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
491 let container = ContainerId::DefWithBodyId(self.def); 522 let container = ContainerId::DefWithBodyId(self.def);
492 for item in block.items() { 523 for item in block.items() {
493 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 524 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
@@ -542,9 +573,16 @@ impl ExprCollector<'_> {
542 self.body.item_scope.define_def(def); 573 self.body.item_scope.define_def(def);
543 if let Some(name) = name { 574 if let Some(name) = name {
544 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 575 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
545 self.body 576 let has_constructor = match def {
546 .item_scope 577 ModuleDefId::AdtId(AdtId::StructId(s)) => {
547 .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); 578 self.db.struct_data(s).variant_data.kind() != StructKind::Record
579 }
580 _ => true,
581 };
582 self.body.item_scope.push_res(
583 name.as_name(),
584 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
585 );
548 } 586 }
549 } 587 }
550 } 588 }
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index ccb682f9a..e7eb2bb11 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,
@@ -40,13 +41,14 @@ impl FunctionData {
40 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { 41 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
41 let loc = func.lookup(db); 42 let loc = func.lookup(db);
42 let src = loc.source(db); 43 let src = loc.source(db);
44 let ctx = LowerCtx::new(db, src.file_id);
43 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); 45 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
44 let mut params = Vec::new(); 46 let mut params = Vec::new();
45 let mut has_self_param = false; 47 let mut has_self_param = false;
46 if let Some(param_list) = src.value.param_list() { 48 if let Some(param_list) = src.value.param_list() {
47 if let Some(self_param) = param_list.self_param() { 49 if let Some(self_param) = param_list.self_param() {
48 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 50 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
49 TypeRef::from_ast(type_ref) 51 TypeRef::from_ast(&ctx, type_ref)
50 } else { 52 } else {
51 let self_type = TypeRef::Path(name![Self].into()); 53 let self_type = TypeRef::Path(name![Self].into());
52 match self_param.kind() { 54 match self_param.kind() {
@@ -63,14 +65,14 @@ impl FunctionData {
63 has_self_param = true; 65 has_self_param = true;
64 } 66 }
65 for param in param_list.params() { 67 for param in param_list.params() {
66 let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); 68 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
67 params.push(type_ref); 69 params.push(type_ref);
68 } 70 }
69 } 71 }
70 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); 72 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id));
71 73
72 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { 74 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
73 TypeRef::from_ast(type_ref) 75 TypeRef::from_ast(&ctx, type_ref)
74 } else { 76 } else {
75 TypeRef::unit() 77 TypeRef::unit()
76 }; 78 };
@@ -122,7 +124,8 @@ impl TypeAliasData {
122 let loc = typ.lookup(db); 124 let loc = typ.lookup(db);
123 let node = loc.source(db); 125 let node = loc.source(db);
124 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); 126 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); 127 let lower_ctx = LowerCtx::new(db, node.file_id);
128 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); 129 let vis_default = RawVisibility::default_for_container(loc.container);
127 let visibility = RawVisibility::from_ast_with_default( 130 let visibility = RawVisibility::from_ast_with_default(
128 db, 131 db,
@@ -130,7 +133,7 @@ impl TypeAliasData {
130 node.as_ref().map(|n| n.visibility()), 133 node.as_ref().map(|n| n.visibility()),
131 ); 134 );
132 let bounds = if let Some(bound_list) = node.value.type_bound_list() { 135 let bounds = if let Some(bound_list) = node.value.type_bound_list() {
133 bound_list.bounds().map(TypeBound::from_ast).collect() 136 bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect()
134 } else { 137 } else {
135 Vec::new() 138 Vec::new()
136 }; 139 };
@@ -147,51 +150,31 @@ pub struct TraitData {
147 150
148impl TraitData { 151impl TraitData {
149 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
150 let src = tr.lookup(db).source(db); 153 let tr_loc = tr.lookup(db);
154 let src = tr_loc.source(db);
151 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 155 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
152 let auto = src.value.auto_token().is_some(); 156 let auto = src.value.auto_token().is_some();
153 let ast_id_map = db.ast_id_map(src.file_id); 157 let module_id = tr_loc.container.module(db);
154 158
155 let container = AssocContainerId::TraitId(tr); 159 let container = AssocContainerId::TraitId(tr);
156 let items = if let Some(item_list) = src.value.item_list() { 160 let mut items = Vec::new();
157 item_list 161
158 .impl_items() 162 if let Some(item_list) = src.value.item_list() {
159 .map(|item_node| match item_node { 163 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
160 ast::ImplItem::FnDef(it) => { 164 items.extend(collect_items(
161 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 165 db,
162 let def = FunctionLoc { 166 &mut expander,
163 container, 167 item_list.assoc_items(),
164 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 168 src.file_id,
165 } 169 container,
166 .intern(db) 170 ));
167 .into(); 171 items.extend(collect_items_in_macros(
168 (name, def) 172 db,
169 } 173 &mut expander,
170 ast::ImplItem::ConstDef(it) => { 174 &src.with_value(item_list),
171 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 175 container,
172 let def = ConstLoc { 176 ));
173 container, 177 }
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 }) 178 Arc::new(TraitData { name, items, auto })
196 } 179 }
197 180
@@ -223,29 +206,28 @@ impl ImplData {
223 let _p = profile("impl_data_query"); 206 let _p = profile("impl_data_query");
224 let impl_loc = id.lookup(db); 207 let impl_loc = id.lookup(db);
225 let src = impl_loc.source(db); 208 let src = impl_loc.source(db);
209 let lower_ctx = LowerCtx::new(db, src.file_id);
226 210
227 let target_trait = src.value.target_trait().map(TypeRef::from_ast); 211 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()); 212 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
229 let is_negative = src.value.excl_token().is_some(); 213 let is_negative = src.value.excl_token().is_some();
230 let module_id = impl_loc.container.module(db); 214 let module_id = impl_loc.container.module(db);
215 let container = AssocContainerId::ImplId(id);
231 216
232 let mut items = Vec::new(); 217 let mut items: Vec<AssocItemId> = Vec::new();
233 218
234 if let Some(item_list) = src.value.item_list() { 219 if let Some(item_list) = src.value.item_list() {
235 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 220 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
236 items.extend(collect_impl_items( 221 items.extend(
237 db, 222 collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container)
238 &mut expander, 223 .into_iter()
239 item_list.impl_items(), 224 .map(|(_, item)| item),
240 src.file_id, 225 );
241 id, 226 items.extend(
242 )); 227 collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
243 items.extend(collect_impl_items_in_macros( 228 .into_iter()
244 db, 229 .map(|(_, item)| item),
245 &mut expander, 230 );
246 &src.with_value(item_list),
247 id,
248 ));
249 } 231 }
250 232
251 let res = ImplData { target_trait, target_type, items, is_negative }; 233 let res = ImplData { target_trait, target_type, items, is_negative };
@@ -279,57 +261,59 @@ impl ConstData {
279 vis_default: RawVisibility, 261 vis_default: RawVisibility,
280 node: InFile<N>, 262 node: InFile<N>,
281 ) -> ConstData { 263 ) -> ConstData {
264 let ctx = LowerCtx::new(db, node.file_id);
282 let name = node.value.name().map(|n| n.as_name()); 265 let name = node.value.name().map(|n| n.as_name());
283 let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type()); 266 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
284 let visibility = 267 let visibility =
285 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); 268 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
286 ConstData { name, type_ref, visibility } 269 ConstData { name, type_ref, visibility }
287 } 270 }
288} 271}
289 272
290fn collect_impl_items_in_macros( 273fn collect_items_in_macros(
291 db: &dyn DefDatabase, 274 db: &dyn DefDatabase,
292 expander: &mut Expander, 275 expander: &mut Expander,
293 impl_def: &InFile<ast::ItemList>, 276 impl_def: &InFile<ast::ItemList>,
294 id: ImplId, 277 container: AssocContainerId,
295) -> Vec<AssocItemId> { 278) -> Vec<(Name, AssocItemId)> {
296 let mut res = Vec::new(); 279 let mut res = Vec::new();
297 280
298 // We set a limit to protect against infinite recursion 281 // We set a limit to protect against infinite recursion
299 let limit = 100; 282 let limit = 100;
300 283
301 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 284 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)) 285 res.extend(collect_items_in_macro(db, expander, m, container, limit))
303 } 286 }
304 287
305 res 288 res
306} 289}
307 290
308fn collect_impl_items_in_macro( 291fn collect_items_in_macro(
309 db: &dyn DefDatabase, 292 db: &dyn DefDatabase,
310 expander: &mut Expander, 293 expander: &mut Expander,
311 m: ast::MacroCall, 294 m: ast::MacroCall,
312 id: ImplId, 295 container: AssocContainerId,
313 limit: usize, 296 limit: usize,
314) -> Vec<AssocItemId> { 297) -> Vec<(Name, AssocItemId)> {
315 if limit == 0 { 298 if limit == 0 {
316 return Vec::new(); 299 return Vec::new();
317 } 300 }
318 301
319 if let Some((mark, items)) = expander.enter_expand(db, None, m) { 302 if let Some((mark, items)) = expander.enter_expand(db, None, m) {
320 let items: InFile<ast::MacroItems> = expander.to_source(items); 303 let items: InFile<ast::MacroItems> = expander.to_source(items);
321 let mut res = collect_impl_items( 304 let mut res = collect_items(
322 db, 305 db,
323 expander, 306 expander,
324 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 307 items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())),
325 items.file_id, 308 items.file_id,
326 id, 309 container,
327 ); 310 );
311
328 // Recursive collect macros 312 // Recursive collect macros
329 // Note that ast::ModuleItem do not include ast::MacroCall 313 // Note that ast::ModuleItem do not include ast::MacroCall
330 // We cannot use ModuleItemOwner::items here 314 // We cannot use ModuleItemOwner::items here
331 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { 315 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)) 316 res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
333 } 317 }
334 expander.exit(db, mark); 318 expander.exit(db, mark);
335 res 319 res
@@ -338,44 +322,38 @@ fn collect_impl_items_in_macro(
338 } 322 }
339} 323}
340 324
341fn collect_impl_items( 325fn collect_items(
342 db: &dyn DefDatabase, 326 db: &dyn DefDatabase,
343 expander: &mut Expander, 327 expander: &mut Expander,
344 impl_items: impl Iterator<Item = ImplItem>, 328 assoc_items: impl Iterator<Item = AssocItem>,
345 file_id: crate::HirFileId, 329 file_id: crate::HirFileId,
346 id: ImplId, 330 container: AssocContainerId,
347) -> Vec<AssocItemId> { 331) -> Vec<(Name, AssocItemId)> {
348 let items = db.ast_id_map(file_id); 332 let items = db.ast_id_map(file_id);
349 333
350 impl_items 334 assoc_items
351 .filter_map(|item_node| match item_node { 335 .filter_map(|item_node| match item_node {
352 ast::ImplItem::FnDef(it) => { 336 ast::AssocItem::FnDef(it) => {
353 let attrs = expander.parse_attrs(&it); 337 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
354 if !expander.is_cfg_enabled(&attrs) { 338 if !expander.is_cfg_enabled(&it) {
355 return None; 339 return None;
356 } 340 }
357 let def = FunctionLoc { 341 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
358 container: AssocContainerId::ImplId(id), 342 .intern(db);
359 ast_id: AstId::new(file_id, items.ast_id(&it)), 343 Some((name, def.into()))
360 }
361 .intern(db);
362 Some(def.into())
363 } 344 }
364 ast::ImplItem::ConstDef(it) => { 345 ast::AssocItem::ConstDef(it) => {
365 let def = ConstLoc { 346 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
366 container: AssocContainerId::ImplId(id), 347 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)), 348 .intern(db);
368 } 349 Some((name, def.into()))
369 .intern(db);
370 Some(def.into())
371 } 350 }
372 ast::ImplItem::TypeAliasDef(it) => { 351 ast::AssocItem::TypeAliasDef(it) => {
373 let def = TypeAliasLoc { 352 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
374 container: AssocContainerId::ImplId(id), 353 let def =
375 ast_id: AstId::new(file_id, items.ast_id(&it)), 354 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
376 } 355 .intern(db);
377 .intern(db); 356 Some((name, def.into()))
378 Some(def.into())
379 } 357 }
380 }) 358 })
381 .collect() 359 .collect()
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/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 98c74fe25..db994122a 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -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);
@@ -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/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 39b011ad7..f2716a295 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -156,9 +156,16 @@ pub(super) struct DefData {
156} 156}
157 157
158#[derive(Debug, PartialEq, Eq, Clone, Copy)] 158#[derive(Debug, PartialEq, Eq, Clone, Copy)]
159pub(super) enum StructDefKind {
160 Record,
161 Tuple,
162 Unit,
163}
164
165#[derive(Debug, PartialEq, Eq, Clone, Copy)]
159pub(super) enum DefKind { 166pub(super) enum DefKind {
160 Function(FileAstId<ast::FnDef>), 167 Function(FileAstId<ast::FnDef>),
161 Struct(FileAstId<ast::StructDef>), 168 Struct(FileAstId<ast::StructDef>, StructDefKind),
162 Union(FileAstId<ast::UnionDef>), 169 Union(FileAstId<ast::UnionDef>),
163 Enum(FileAstId<ast::EnumDef>), 170 Enum(FileAstId<ast::EnumDef>),
164 Const(FileAstId<ast::ConstDef>), 171 Const(FileAstId<ast::ConstDef>),
@@ -171,7 +178,7 @@ impl DefKind {
171 pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> { 178 pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> {
172 match self { 179 match self {
173 DefKind::Function(it) => it.upcast(), 180 DefKind::Function(it) => it.upcast(),
174 DefKind::Struct(it) => it.upcast(), 181 DefKind::Struct(it, _) => it.upcast(),
175 DefKind::Union(it) => it.upcast(), 182 DefKind::Union(it) => it.upcast(),
176 DefKind::Enum(it) => it.upcast(), 183 DefKind::Enum(it) => it.upcast(),
177 DefKind::Const(it) => it.upcast(), 184 DefKind::Const(it) => it.upcast(),
@@ -188,6 +195,7 @@ pub(super) struct MacroData {
188 pub(super) path: ModPath, 195 pub(super) path: ModPath,
189 pub(super) name: Option<Name>, 196 pub(super) name: Option<Name>,
190 pub(super) export: bool, 197 pub(super) export: bool,
198 pub(super) local_inner: bool,
191 pub(super) builtin: bool, 199 pub(super) builtin: bool,
192} 200}
193 201
@@ -235,9 +243,14 @@ impl RawItemsCollector {
235 return; 243 return;
236 } 244 }
237 ast::ModuleItem::StructDef(it) => { 245 ast::ModuleItem::StructDef(it) => {
246 let kind = match it.kind() {
247 ast::StructKind::Record(_) => StructDefKind::Record,
248 ast::StructKind::Tuple(_) => StructDefKind::Tuple,
249 ast::StructKind::Unit => StructDefKind::Unit,
250 };
238 let id = self.source_ast_id_map.ast_id(&it); 251 let id = self.source_ast_id_map.ast_id(&it);
239 let name = it.name(); 252 let name = it.name();
240 (DefKind::Struct(id), name) 253 (DefKind::Struct(id, kind), name)
241 } 254 }
242 ast::ModuleItem::UnionDef(it) => { 255 ast::ModuleItem::UnionDef(it) => {
243 let id = self.source_ast_id_map.ast_id(&it); 256 let id = self.source_ast_id_map.ast_id(&it);
@@ -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..1b66c1aac 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -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}
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs
index b0befdfbd..40289e3ca 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 "###);
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/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index f308c6bdf..5bdad9efd 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 {
@@ -64,30 +64,34 @@ pub enum TypeBound {
64 64
65impl TypeRef { 65impl TypeRef {
66 /// Converts an `ast::TypeRef` to a `hir::TypeRef`. 66 /// Converts an `ast::TypeRef` to a `hir::TypeRef`.
67 pub(crate) fn from_ast(node: ast::TypeRef) -> Self { 67 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeRef) -> Self {
68 match node { 68 match node {
69 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), 69 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
70 ast::TypeRef::TupleType(inner) => { 70 ast::TypeRef::TupleType(inner) => {
71 TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect()) 71 TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect())
72 } 72 }
73 ast::TypeRef::NeverType(..) => TypeRef::Never, 73 ast::TypeRef::NeverType(..) => TypeRef::Never,
74 ast::TypeRef::PathType(inner) => { 74 ast::TypeRef::PathType(inner) => {
75 // FIXME: Use `Path::from_src` 75 // FIXME: Use `Path::from_src`
76 inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error) 76 inner
77 .path()
78 .and_then(|it| ctx.lower_path(it))
79 .map(TypeRef::Path)
80 .unwrap_or(TypeRef::Error)
77 } 81 }
78 ast::TypeRef::PointerType(inner) => { 82 ast::TypeRef::PointerType(inner) => {
79 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 83 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
80 let mutability = Mutability::from_mutable(inner.mut_token().is_some()); 84 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
81 TypeRef::RawPtr(Box::new(inner_ty), mutability) 85 TypeRef::RawPtr(Box::new(inner_ty), mutability)
82 } 86 }
83 ast::TypeRef::ArrayType(inner) => { 87 ast::TypeRef::ArrayType(inner) => {
84 TypeRef::Array(Box::new(TypeRef::from_ast_opt(inner.type_ref()))) 88 TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
85 } 89 }
86 ast::TypeRef::SliceType(inner) => { 90 ast::TypeRef::SliceType(inner) => {
87 TypeRef::Slice(Box::new(TypeRef::from_ast_opt(inner.type_ref()))) 91 TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
88 } 92 }
89 ast::TypeRef::ReferenceType(inner) => { 93 ast::TypeRef::ReferenceType(inner) => {
90 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 94 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
91 let mutability = Mutability::from_mutable(inner.mut_token().is_some()); 95 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
92 TypeRef::Reference(Box::new(inner_ty), mutability) 96 TypeRef::Reference(Box::new(inner_ty), mutability)
93 } 97 }
@@ -96,10 +100,13 @@ impl TypeRef {
96 let ret_ty = inner 100 let ret_ty = inner
97 .ret_type() 101 .ret_type()
98 .and_then(|rt| rt.type_ref()) 102 .and_then(|rt| rt.type_ref())
99 .map(TypeRef::from_ast) 103 .map(|it| TypeRef::from_ast(ctx, it))
100 .unwrap_or_else(|| TypeRef::Tuple(Vec::new())); 104 .unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
101 let mut params = if let Some(pl) = inner.param_list() { 105 let mut params = if let Some(pl) = inner.param_list() {
102 pl.params().map(|p| p.ascribed_type()).map(TypeRef::from_ast_opt).collect() 106 pl.params()
107 .map(|p| p.ascribed_type())
108 .map(|it| TypeRef::from_ast_opt(&ctx, it))
109 .collect()
103 } else { 110 } else {
104 Vec::new() 111 Vec::new()
105 }; 112 };
@@ -107,19 +114,19 @@ impl TypeRef {
107 TypeRef::Fn(params) 114 TypeRef::Fn(params)
108 } 115 }
109 // for types are close enough for our purposes to the inner type for now... 116 // 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()), 117 ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
111 ast::TypeRef::ImplTraitType(inner) => { 118 ast::TypeRef::ImplTraitType(inner) => {
112 TypeRef::ImplTrait(type_bounds_from_ast(inner.type_bound_list())) 119 TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
113 } 120 }
114 ast::TypeRef::DynTraitType(inner) => { 121 ast::TypeRef::DynTraitType(inner) => {
115 TypeRef::DynTrait(type_bounds_from_ast(inner.type_bound_list())) 122 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
116 } 123 }
117 } 124 }
118 } 125 }
119 126
120 pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { 127 pub(crate) fn from_ast_opt(ctx: &LowerCtx, node: Option<ast::TypeRef>) -> Self {
121 if let Some(node) = node { 128 if let Some(node) = node {
122 TypeRef::from_ast(node) 129 TypeRef::from_ast(ctx, node)
123 } else { 130 } else {
124 TypeRef::Error 131 TypeRef::Error
125 } 132 }
@@ -180,24 +187,27 @@ impl TypeRef {
180 } 187 }
181} 188}
182 189
183pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { 190pub(crate) fn type_bounds_from_ast(
191 lower_ctx: &LowerCtx,
192 type_bounds_opt: Option<ast::TypeBoundList>,
193) -> Vec<TypeBound> {
184 if let Some(type_bounds) = type_bounds_opt { 194 if let Some(type_bounds) = type_bounds_opt {
185 type_bounds.bounds().map(TypeBound::from_ast).collect() 195 type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
186 } else { 196 } else {
187 vec![] 197 vec![]
188 } 198 }
189} 199}
190 200
191impl TypeBound { 201impl TypeBound {
192 pub(crate) fn from_ast(node: ast::TypeBound) -> Self { 202 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeBound) -> Self {
193 match node.kind() { 203 match node.kind() {
194 ast::TypeBoundKind::PathType(path_type) => { 204 ast::TypeBoundKind::PathType(path_type) => {
195 let path = match path_type.path() { 205 let path = match path_type.path() {
196 Some(p) => p, 206 Some(p) => p,
197 None => return TypeBound::Error, 207 None => return TypeBound::Error,
198 }; 208 };
199 // FIXME: Use `Path::from_src` 209
200 let path = match Path::from_ast(path) { 210 let path = match ctx.lower_path(path) {
201 Some(p) => p, 211 Some(p) => p,
202 None => return TypeBound::Error, 212 None => return TypeBound::Error,
203 }; 213 };