aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/adt.rs18
-rw-r--r--crates/ra_hir_def/src/attr.rs1
-rw-r--r--crates/ra_hir_def/src/body.rs2
-rw-r--r--crates/ra_hir_def/src/body/lower.rs63
-rw-r--r--crates/ra_hir_def/src/data.rs21
-rw-r--r--crates/ra_hir_def/src/expr.rs4
-rw-r--r--crates/ra_hir_def/src/generics.rs68
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs2
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs29
-rw-r--r--crates/ra_hir_def/src/nameres/tests/macros.rs37
-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
13 files changed, 255 insertions, 85 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 753becc3d..8eef51828 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!
@@ -198,6 +204,8 @@ fn lower_struct(
198 trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, 204 trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
199 ast: &InFile<ast::StructKind>, 205 ast: &InFile<ast::StructKind>,
200) -> StructKind { 206) -> StructKind {
207 let ctx = LowerCtx::new(db, ast.file_id);
208
201 match &ast.value { 209 match &ast.value {
202 ast::StructKind::Tuple(fl) => { 210 ast::StructKind::Tuple(fl) => {
203 for (i, fd) in fl.fields().enumerate() { 211 for (i, fd) in fl.fields().enumerate() {
@@ -210,7 +218,7 @@ fn lower_struct(
210 || Either::Left(fd.clone()), 218 || Either::Left(fd.clone()),
211 || FieldData { 219 || FieldData {
212 name: Name::new_tuple_field(i), 220 name: Name::new_tuple_field(i),
213 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 221 type_ref: TypeRef::from_ast_opt(&ctx, fd.type_ref()),
214 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 222 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
215 }, 223 },
216 ); 224 );
@@ -228,7 +236,7 @@ fn lower_struct(
228 || Either::Right(fd.clone()), 236 || Either::Right(fd.clone()),
229 || FieldData { 237 || FieldData {
230 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 238 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
231 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 239 type_ref: TypeRef::from_ast_opt(&ctx, fd.ascribed_type()),
232 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 240 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
233 }, 241 },
234 ); 242 );
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 890cefcaf..4edaad960 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,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index f467ed3fe..687216dc3 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}
@@ -182,6 +203,16 @@ impl ExprCollector<'_> {
182 203
183 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) 204 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
184 } 205 }
206 ast::Expr::EffectExpr(e) => match e.effect() {
207 ast::Effect::Try(_) => {
208 let body = self.collect_block_opt(e.block_expr());
209 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
210 }
211 // FIXME: we need to record these effects somewhere...
212 ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => {
213 self.collect_block_opt(e.block_expr())
214 }
215 },
185 ast::Expr::BlockExpr(e) => self.collect_block(e), 216 ast::Expr::BlockExpr(e) => self.collect_block(e),
186 ast::Expr::LoopExpr(e) => { 217 ast::Expr::LoopExpr(e) => {
187 let body = self.collect_block_opt(e.loop_body()); 218 let body = self.collect_block_opt(e.loop_body());
@@ -237,7 +268,8 @@ impl ExprCollector<'_> {
237 Vec::new() 268 Vec::new()
238 }; 269 };
239 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 270 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); 271 let generic_args =
272 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it));
241 self.alloc_expr( 273 self.alloc_expr(
242 Expr::MethodCall { receiver, method_name, args, generic_args }, 274 Expr::MethodCall { receiver, method_name, args, generic_args },
243 syntax_ptr, 275 syntax_ptr,
@@ -343,7 +375,7 @@ impl ExprCollector<'_> {
343 } 375 }
344 ast::Expr::CastExpr(e) => { 376 ast::Expr::CastExpr(e) => {
345 let expr = self.collect_expr_opt(e.expr()); 377 let expr = self.collect_expr_opt(e.expr());
346 let type_ref = TypeRef::from_ast_opt(e.type_ref()); 378 let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref());
347 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 379 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
348 } 380 }
349 ast::Expr::RefExpr(e) => { 381 ast::Expr::RefExpr(e) => {
@@ -365,12 +397,16 @@ impl ExprCollector<'_> {
365 if let Some(pl) = e.param_list() { 397 if let Some(pl) = e.param_list() {
366 for param in pl.params() { 398 for param in pl.params() {
367 let pat = self.collect_pat_opt(param.pat()); 399 let pat = self.collect_pat_opt(param.pat());
368 let type_ref = param.ascribed_type().map(TypeRef::from_ast); 400 let type_ref =
401 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
369 args.push(pat); 402 args.push(pat);
370 arg_types.push(type_ref); 403 arg_types.push(type_ref);
371 } 404 }
372 } 405 }
373 let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); 406 let ret_type = e
407 .ret_type()
408 .and_then(|r| r.type_ref())
409 .map(|it| TypeRef::from_ast(&self.ctx, it));
374 let body = self.collect_expr_opt(e.body()); 410 let body = self.collect_expr_opt(e.body());
375 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 411 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
376 } 412 }
@@ -430,6 +466,7 @@ impl ExprCollector<'_> {
430 krate: Some(self.expander.module.krate), 466 krate: Some(self.expander.module.krate),
431 ast_id: Some(self.expander.ast_id(&e)), 467 ast_id: Some(self.expander.ast_id(&e)),
432 kind: MacroDefKind::Declarative, 468 kind: MacroDefKind::Declarative,
469 local_inner: false,
433 }; 470 };
434 self.body.item_scope.define_legacy_macro(name, mac); 471 self.body.item_scope.define_legacy_macro(name, mac);
435 472
@@ -464,19 +501,15 @@ impl ExprCollector<'_> {
464 } 501 }
465 } 502 }
466 503
467 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { 504 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
468 let syntax_node_ptr = AstPtr::new(&expr.clone().into()); 505 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); 506 self.collect_block_items(&block);
474 let statements = block 507 let statements = block
475 .statements() 508 .statements()
476 .map(|s| match s { 509 .map(|s| match s {
477 ast::Stmt::LetStmt(stmt) => { 510 ast::Stmt::LetStmt(stmt) => {
478 let pat = self.collect_pat_opt(stmt.pat()); 511 let pat = self.collect_pat_opt(stmt.pat());
479 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); 512 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)); 513 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
481 Statement::Let { pat, type_ref, initializer } 514 Statement::Let { pat, type_ref, initializer }
482 } 515 }
@@ -487,7 +520,7 @@ impl ExprCollector<'_> {
487 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 520 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
488 } 521 }
489 522
490 fn collect_block_items(&mut self, block: &ast::Block) { 523 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
491 let container = ContainerId::DefWithBodyId(self.def); 524 let container = ContainerId::DefWithBodyId(self.def);
492 for item in block.items() { 525 for item in block.items() {
493 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 526 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index ccb682f9a..7a2067e49 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -15,6 +15,7 @@ use ra_syntax::ast::{
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 };
@@ -223,9 +226,10 @@ impl ImplData {
223 let _p = profile("impl_data_query"); 226 let _p = profile("impl_data_query");
224 let impl_loc = id.lookup(db); 227 let impl_loc = id.lookup(db);
225 let src = impl_loc.source(db); 228 let src = impl_loc.source(db);
229 let lower_ctx = LowerCtx::new(db, src.file_id);
226 230
227 let target_trait = src.value.target_trait().map(TypeRef::from_ast); 231 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()); 232 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
229 let is_negative = src.value.excl_token().is_some(); 233 let is_negative = src.value.excl_token().is_some();
230 let module_id = impl_loc.container.module(db); 234 let module_id = impl_loc.container.module(db);
231 235
@@ -279,8 +283,9 @@ impl ConstData {
279 vis_default: RawVisibility, 283 vis_default: RawVisibility,
280 node: InFile<N>, 284 node: InFile<N>,
281 ) -> ConstData { 285 ) -> ConstData {
286 let ctx = LowerCtx::new(db, node.file_id);
282 let name = node.value.name().map(|n| n.as_name()); 287 let name = node.value.name().map(|n| n.as_name());
283 let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type()); 288 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
284 let visibility = 289 let visibility =
285 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); 290 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
286 ConstData { name, type_ref, visibility } 291 ConstData { name, type_ref, visibility }
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index aad12e123..a0cdad529 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -101,6 +101,9 @@ pub enum Expr {
101 Try { 101 Try {
102 expr: ExprId, 102 expr: ExprId,
103 }, 103 },
104 TryBlock {
105 body: ExprId,
106 },
104 Cast { 107 Cast {
105 expr: ExprId, 108 expr: ExprId,
106 type_ref: TypeRef, 109 type_ref: TypeRef,
@@ -236,6 +239,7 @@ impl Expr {
236 f(*expr); 239 f(*expr);
237 } 240 }
238 } 241 }
242 Expr::TryBlock { body } => f(*body),
239 Expr::Loop { body } => f(*body), 243 Expr::Loop { body } => f(*body),
240 Expr::While { condition, body } => { 244 Expr::While { condition, body } => {
241 f(*condition); 245 f(*condition);
diff --git a/crates/ra_hir_def/src/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/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 98c74fe25..bf3968bd6 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);
@@ -941,6 +942,7 @@ impl ModCollector<'_, '_> {
941 ast_id: Some(ast_id.ast_id), 942 ast_id: Some(ast_id.ast_id),
942 krate: Some(self.def_collector.def_map.krate), 943 krate: Some(self.def_collector.def_map.krate),
943 kind: MacroDefKind::Declarative, 944 kind: MacroDefKind::Declarative,
945 local_inner: mac.local_inner,
944 }; 946 };
945 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); 947 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
946 } 948 }
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 39b011ad7..a71503c76 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -188,6 +188,7 @@ pub(super) struct MacroData {
188 pub(super) path: ModPath, 188 pub(super) path: ModPath,
189 pub(super) name: Option<Name>, 189 pub(super) name: Option<Name>,
190 pub(super) export: bool, 190 pub(super) export: bool,
191 pub(super) local_inner: bool,
191 pub(super) builtin: bool, 192 pub(super) builtin: bool,
192} 193}
193 194
@@ -401,14 +402,32 @@ impl RawItemsCollector {
401 402
402 let name = m.name().map(|it| it.as_name()); 403 let name = m.name().map(|it| it.as_name());
403 let ast_id = self.source_ast_id_map.ast_id(&m); 404 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 405
407 // FIXME: cfg_attr 406 // FIXME: cfg_attr
408 let builtin = 407 let export_attr = attrs.by_key("macro_export");
409 m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "rustc_builtin_macro"); 408
409 let export = export_attr.exists();
410 let local_inner = if export {
411 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
412 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
413 ident.text.contains("local_inner_macros")
414 }
415 _ => false,
416 })
417 } else {
418 false
419 };
420
421 let builtin = attrs.by_key("rustc_builtin_macro").exists();
410 422
411 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export, builtin }); 423 let m = self.raw_items.macros.alloc(MacroData {
424 ast_id,
425 path,
426 name,
427 export,
428 local_inner,
429 builtin,
430 });
412 self.push_item(current_module, attrs, RawItemKind::Macro(m)); 431 self.push_item(current_module, attrs, RawItemKind::Macro(m));
413 } 432 }
414 433
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs
index b0befdfbd..9bc0e6287 100644
--- a/crates/ra_hir_def/src/nameres/tests/macros.rs
+++ b/crates/ra_hir_def/src/nameres/tests/macros.rs
@@ -136,6 +136,43 @@ fn macro_rules_export_with_local_inner_macros_are_visible() {
136} 136}
137 137
138#[test] 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 v
165 â‹®Foo: t v
166 â‹®bar: t
167 â‹®
168 â‹®crate::bar
169 â‹®Bar: t v
170 â‹®Foo: t v
171 â‹®bar: t
172 "###);
173}
174
175#[test]
139fn unexpanded_macro_should_expand_by_fixedpoint_loop() { 176fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
140 let map = def_map( 177 let map = def_map(
141 " 178 "
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 };