diff options
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 54 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/scope.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/expr.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 63 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 79 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 6 |
7 files changed, 156 insertions, 94 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 142c52d35..010d35e55 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -7,9 +7,7 @@ use std::{mem, ops::Index, sync::Arc}; | |||
7 | 7 | ||
8 | use drop_bomb::DropBomb; | 8 | use drop_bomb::DropBomb; |
9 | use either::Either; | 9 | use either::Either; |
10 | use hir_expand::{ | 10 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId}; |
11 | ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, | ||
12 | }; | ||
13 | use ra_arena::{map::ArenaMap, Arena}; | 11 | use ra_arena::{map::ArenaMap, Arena}; |
14 | use ra_prof::profile; | 12 | use ra_prof::profile; |
15 | use ra_syntax::{ast, AstNode, AstPtr}; | 13 | use ra_syntax::{ast, AstNode, AstPtr}; |
@@ -23,7 +21,7 @@ use crate::{ | |||
23 | nameres::CrateDefMap, | 21 | nameres::CrateDefMap, |
24 | path::{ModPath, Path}, | 22 | path::{ModPath, Path}, |
25 | src::HasSource, | 23 | src::HasSource, |
26 | DefWithBodyId, HasModule, Lookup, ModuleId, | 24 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, |
27 | }; | 25 | }; |
28 | 26 | ||
29 | pub(crate) struct Expander { | 27 | pub(crate) struct Expander { |
@@ -51,30 +49,26 @@ impl Expander { | |||
51 | db: &DB, | 49 | db: &DB, |
52 | macro_call: ast::MacroCall, | 50 | macro_call: ast::MacroCall, |
53 | ) -> Option<(Mark, T)> { | 51 | ) -> Option<(Mark, T)> { |
54 | let ast_id = AstId::new( | 52 | let macro_call = InFile::new(self.current_file_id, ¯o_call); |
55 | self.current_file_id, | 53 | |
56 | db.ast_id_map(self.current_file_id).ast_id(¯o_call), | 54 | if let Some(call_id) = |
57 | ); | 55 | macro_call.as_call_id(db, |path| self.resolve_path_as_macro(db, &path)) |
58 | 56 | { | |
59 | if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) { | 57 | let file_id = call_id.as_file(); |
60 | if let Some(def) = self.resolve_path_as_macro(db, &path) { | 58 | if let Some(node) = db.parse_or_expand(file_id) { |
61 | let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); | 59 | if let Some(expr) = T::cast(node) { |
62 | let file_id = call_id.as_file(); | 60 | log::debug!("macro expansion {:#?}", expr.syntax()); |
63 | if let Some(node) = db.parse_or_expand(file_id) { | 61 | |
64 | if let Some(expr) = T::cast(node) { | 62 | let mark = Mark { |
65 | log::debug!("macro expansion {:#?}", expr.syntax()); | 63 | file_id: self.current_file_id, |
66 | 64 | ast_id_map: mem::take(&mut self.ast_id_map), | |
67 | let mark = Mark { | 65 | bomb: DropBomb::new("expansion mark dropped"), |
68 | file_id: self.current_file_id, | 66 | }; |
69 | ast_id_map: mem::take(&mut self.ast_id_map), | 67 | self.hygiene = Hygiene::new(db, file_id); |
70 | bomb: DropBomb::new("expansion mark dropped"), | 68 | self.current_file_id = file_id; |
71 | }; | 69 | self.ast_id_map = db.ast_id_map(file_id); |
72 | self.hygiene = Hygiene::new(db, file_id); | 70 | |
73 | self.current_file_id = file_id; | 71 | return Some((mark, expr)); |
74 | self.ast_id_map = db.ast_id_map(file_id); | ||
75 | |||
76 | return Some((mark, expr)); | ||
77 | } | ||
78 | } | 72 | } |
79 | } | 73 | } |
80 | } | 74 | } |
@@ -99,10 +93,6 @@ impl Expander { | |||
99 | Path::from_src(path, &self.hygiene) | 93 | Path::from_src(path, &self.hygiene) |
100 | } | 94 | } |
101 | 95 | ||
102 | fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> { | ||
103 | ModPath::from_src(path, &self.hygiene) | ||
104 | } | ||
105 | |||
106 | fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> { | 96 | fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> { |
107 | self.crate_def_map | 97 | self.crate_def_map |
108 | .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) | 98 | .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index e656f9a41..1fc892362 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -8,7 +8,7 @@ use ra_arena::Arena; | |||
8 | use ra_syntax::{ | 8 | use ra_syntax::{ |
9 | ast::{ | 9 | ast::{ |
10 | self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, | 10 | self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, |
11 | TypeAscriptionOwner, | 11 | SlicePatComponents, TypeAscriptionOwner, |
12 | }, | 12 | }, |
13 | AstNode, AstPtr, | 13 | AstNode, AstPtr, |
14 | }; | 14 | }; |
@@ -164,9 +164,9 @@ where | |||
164 | let match_expr = self.collect_expr_opt(condition.expr()); | 164 | let match_expr = self.collect_expr_opt(condition.expr()); |
165 | let placeholder_pat = self.missing_pat(); | 165 | let placeholder_pat = self.missing_pat(); |
166 | let arms = vec![ | 166 | let arms = vec![ |
167 | MatchArm { pats: vec![pat], expr: then_branch, guard: None }, | 167 | MatchArm { pat, expr: then_branch, guard: None }, |
168 | MatchArm { | 168 | MatchArm { |
169 | pats: vec![placeholder_pat], | 169 | pat: placeholder_pat, |
170 | expr: else_branch.unwrap_or_else(|| self.empty_block()), | 170 | expr: else_branch.unwrap_or_else(|| self.empty_block()), |
171 | guard: None, | 171 | guard: None, |
172 | }, | 172 | }, |
@@ -203,8 +203,8 @@ where | |||
203 | let placeholder_pat = self.missing_pat(); | 203 | let placeholder_pat = self.missing_pat(); |
204 | let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); | 204 | let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); |
205 | let arms = vec![ | 205 | let arms = vec![ |
206 | MatchArm { pats: vec![pat], expr: body, guard: None }, | 206 | MatchArm { pat, expr: body, guard: None }, |
207 | MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None }, | 207 | MatchArm { pat: placeholder_pat, expr: break_, guard: None }, |
208 | ]; | 208 | ]; |
209 | let match_expr = | 209 | let match_expr = |
210 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); | 210 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); |
@@ -250,7 +250,7 @@ where | |||
250 | match_arm_list | 250 | match_arm_list |
251 | .arms() | 251 | .arms() |
252 | .map(|arm| MatchArm { | 252 | .map(|arm| MatchArm { |
253 | pats: arm.pats().map(|p| self.collect_pat(p)).collect(), | 253 | pat: self.collect_pat_opt(arm.pat()), |
254 | expr: self.collect_expr_opt(arm.expr()), | 254 | expr: self.collect_expr_opt(arm.expr()), |
255 | guard: arm | 255 | guard: arm |
256 | .guard() | 256 | .guard() |
@@ -587,11 +587,16 @@ where | |||
587 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 587 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
588 | path.map(Pat::Path).unwrap_or(Pat::Missing) | 588 | path.map(Pat::Path).unwrap_or(Pat::Missing) |
589 | } | 589 | } |
590 | ast::Pat::OrPat(p) => { | ||
591 | let pats = p.pats().map(|p| self.collect_pat(p)).collect(); | ||
592 | Pat::Or(pats) | ||
593 | } | ||
594 | ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), | ||
590 | ast::Pat::TuplePat(p) => { | 595 | ast::Pat::TuplePat(p) => { |
591 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 596 | let args = p.args().map(|p| self.collect_pat(p)).collect(); |
592 | Pat::Tuple(args) | 597 | Pat::Tuple(args) |
593 | } | 598 | } |
594 | ast::Pat::PlaceholderPat(_) => Pat::Wild, | 599 | ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild, |
595 | ast::Pat::RecordPat(p) => { | 600 | ast::Pat::RecordPat(p) => { |
596 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 601 | let path = p.path().and_then(|path| self.expander.parse_path(path)); |
597 | let record_field_pat_list = | 602 | let record_field_pat_list = |
@@ -616,12 +621,20 @@ where | |||
616 | 621 | ||
617 | Pat::Record { path, args: fields } | 622 | Pat::Record { path, args: fields } |
618 | } | 623 | } |
624 | ast::Pat::SlicePat(p) => { | ||
625 | let SlicePatComponents { prefix, slice, suffix } = p.components(); | ||
626 | |||
627 | Pat::Slice { | ||
628 | prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(), | ||
629 | slice: slice.map(|p| self.collect_pat(p)), | ||
630 | suffix: suffix.into_iter().map(|p| self.collect_pat(p)).collect(), | ||
631 | } | ||
632 | } | ||
619 | 633 | ||
620 | // FIXME: implement | 634 | // FIXME: implement |
621 | ast::Pat::DotDotPat(_) => Pat::Missing, | ||
622 | ast::Pat::BoxPat(_) => Pat::Missing, | 635 | ast::Pat::BoxPat(_) => Pat::Missing, |
623 | ast::Pat::LiteralPat(_) => Pat::Missing, | 636 | ast::Pat::LiteralPat(_) => Pat::Missing, |
624 | ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing, | 637 | ast::Pat::RangePat(_) => Pat::Missing, |
625 | }; | 638 | }; |
626 | let ptr = AstPtr::new(&pat); | 639 | let ptr = AstPtr::new(&pat); |
627 | self.alloc_pat(pattern, Either::Left(ptr)) | 640 | self.alloc_pat(pattern, Either::Left(ptr)) |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index a63552327..a58a7b21f 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -158,9 +158,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope | |||
158 | compute_expr_scopes(*expr, body, scopes, scope); | 158 | compute_expr_scopes(*expr, body, scopes, scope); |
159 | for arm in arms { | 159 | for arm in arms { |
160 | let scope = scopes.new_scope(scope); | 160 | let scope = scopes.new_scope(scope); |
161 | for pat in &arm.pats { | 161 | scopes.add_bindings(body, scope, arm.pat); |
162 | scopes.add_bindings(body, scope, *pat); | ||
163 | } | ||
164 | scopes.set_scope(arm.expr, scope); | 162 | scopes.set_scope(arm.expr, scope); |
165 | compute_expr_scopes(arm.expr, body, scopes, scope); | 163 | compute_expr_scopes(arm.expr, body, scopes, scope); |
166 | } | 164 | } |
@@ -194,7 +192,7 @@ mod tests { | |||
194 | let (off, code) = extract_offset(code); | 192 | let (off, code) = extract_offset(code); |
195 | let code = { | 193 | let code = { |
196 | let mut buf = String::new(); | 194 | let mut buf = String::new(); |
197 | let off = u32::from(off) as usize; | 195 | let off = off.to_usize(); |
198 | buf.push_str(&code[..off]); | 196 | buf.push_str(&code[..off]); |
199 | buf.push_str("marker"); | 197 | buf.push_str("marker"); |
200 | buf.push_str(&code[off..]); | 198 | buf.push_str(&code[off..]); |
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index a75ef9970..9707c5527 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -202,7 +202,7 @@ pub enum Array { | |||
202 | 202 | ||
203 | #[derive(Debug, Clone, Eq, PartialEq)] | 203 | #[derive(Debug, Clone, Eq, PartialEq)] |
204 | pub struct MatchArm { | 204 | pub struct MatchArm { |
205 | pub pats: Vec<PatId>, | 205 | pub pat: PatId, |
206 | pub guard: Option<ExprId>, | 206 | pub guard: Option<ExprId>, |
207 | pub expr: ExprId, | 207 | pub expr: ExprId, |
208 | } | 208 | } |
@@ -382,6 +382,7 @@ pub enum Pat { | |||
382 | Missing, | 382 | Missing, |
383 | Wild, | 383 | Wild, |
384 | Tuple(Vec<PatId>), | 384 | Tuple(Vec<PatId>), |
385 | Or(Vec<PatId>), | ||
385 | Record { | 386 | Record { |
386 | path: Option<Path>, | 387 | path: Option<Path>, |
387 | args: Vec<RecordFieldPat>, | 388 | args: Vec<RecordFieldPat>, |
@@ -393,7 +394,7 @@ pub enum Pat { | |||
393 | }, | 394 | }, |
394 | Slice { | 395 | Slice { |
395 | prefix: Vec<PatId>, | 396 | prefix: Vec<PatId>, |
396 | rest: Option<PatId>, | 397 | slice: Option<PatId>, |
397 | suffix: Vec<PatId>, | 398 | suffix: Vec<PatId>, |
398 | }, | 399 | }, |
399 | Path(Path), | 400 | Path(Path), |
@@ -420,12 +421,12 @@ impl Pat { | |||
420 | Pat::Bind { subpat, .. } => { | 421 | Pat::Bind { subpat, .. } => { |
421 | subpat.iter().copied().for_each(f); | 422 | subpat.iter().copied().for_each(f); |
422 | } | 423 | } |
423 | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { | 424 | Pat::Or(args) | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { |
424 | args.iter().copied().for_each(f); | 425 | args.iter().copied().for_each(f); |
425 | } | 426 | } |
426 | Pat::Ref { pat, .. } => f(*pat), | 427 | Pat::Ref { pat, .. } => f(*pat), |
427 | Pat::Slice { prefix, rest, suffix } => { | 428 | Pat::Slice { prefix, slice, suffix } => { |
428 | let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter()); | 429 | let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter()); |
429 | total_iter.copied().for_each(f); | 430 | total_iter.copied().for_each(f); |
430 | } | 431 | } |
431 | Pat::Record { args, .. } => { | 432 | Pat::Record { args, .. } => { |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index feb3a300d..aa0b558b8 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -46,7 +46,10 @@ mod marks; | |||
46 | 46 | ||
47 | use std::hash::Hash; | 47 | use std::hash::Hash; |
48 | 48 | ||
49 | use hir_expand::{ast_id_map::FileAstId, AstId, HirFileId, InFile, MacroDefId}; | 49 | use hir_expand::{ |
50 | ast_id_map::FileAstId, db::AstDatabase, hygiene::Hygiene, AstId, HirFileId, InFile, | ||
51 | MacroCallId, MacroCallKind, MacroDefId, | ||
52 | }; | ||
50 | use ra_arena::{impl_arena_id, RawId}; | 53 | use ra_arena::{impl_arena_id, RawId}; |
51 | use ra_db::{impl_intern_key, salsa, CrateId}; | 54 | use ra_db::{impl_intern_key, salsa, CrateId}; |
52 | use ra_syntax::{ast, AstNode}; | 55 | use ra_syntax::{ast, AstNode}; |
@@ -413,3 +416,61 @@ impl HasModule for StaticLoc { | |||
413 | self.container.module(db) | 416 | self.container.module(db) |
414 | } | 417 | } |
415 | } | 418 | } |
419 | |||
420 | /// A helper trait for converting to MacroCallId | ||
421 | pub trait AsMacroCall { | ||
422 | fn as_call_id( | ||
423 | &self, | ||
424 | db: &(impl db::DefDatabase + AstDatabase), | ||
425 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
426 | ) -> Option<MacroCallId>; | ||
427 | } | ||
428 | |||
429 | impl AsMacroCall for InFile<&ast::MacroCall> { | ||
430 | fn as_call_id( | ||
431 | &self, | ||
432 | db: &(impl db::DefDatabase + AstDatabase), | ||
433 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
434 | ) -> Option<MacroCallId> { | ||
435 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); | ||
436 | let h = Hygiene::new(db, self.file_id); | ||
437 | let path = path::ModPath::from_src(self.value.path()?, &h)?; | ||
438 | |||
439 | AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, resolver) | ||
440 | } | ||
441 | } | ||
442 | |||
443 | /// Helper wrapper for `AstId` with `ModPath` | ||
444 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
445 | struct AstIdWithPath<T: ast::AstNode> { | ||
446 | pub ast_id: AstId<T>, | ||
447 | pub path: path::ModPath, | ||
448 | } | ||
449 | |||
450 | impl<T: ast::AstNode> AstIdWithPath<T> { | ||
451 | pub fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T> { | ||
452 | AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path } | ||
453 | } | ||
454 | } | ||
455 | |||
456 | impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | ||
457 | fn as_call_id( | ||
458 | &self, | ||
459 | db: &impl AstDatabase, | ||
460 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
461 | ) -> Option<MacroCallId> { | ||
462 | let def = resolver(self.path.clone())?; | ||
463 | Some(def.as_call_id(db, MacroCallKind::FnLike(self.ast_id.clone()))) | ||
464 | } | ||
465 | } | ||
466 | |||
467 | impl AsMacroCall for AstIdWithPath<ast::ModuleItem> { | ||
468 | fn as_call_id( | ||
469 | &self, | ||
470 | db: &impl AstDatabase, | ||
471 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
472 | ) -> Option<MacroCallId> { | ||
473 | let def = resolver(self.path.clone())?; | ||
474 | Some(def.as_call_id(db, MacroCallKind::Attr(self.ast_id.clone()))) | ||
475 | } | ||
476 | } | ||
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 6352c71ef..51c65a5d7 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -7,7 +7,7 @@ use hir_expand::{ | |||
7 | builtin_derive::find_builtin_derive, | 7 | builtin_derive::find_builtin_derive, |
8 | builtin_macro::find_builtin_macro, | 8 | builtin_macro::find_builtin_macro, |
9 | name::{name, AsName, Name}, | 9 | name::{name, AsName, Name}, |
10 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 10 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, |
11 | }; | 11 | }; |
12 | use ra_cfg::CfgOptions; | 12 | use ra_cfg::CfgOptions; |
13 | use ra_db::{CrateId, FileId}; | 13 | use ra_db::{CrateId, FileId}; |
@@ -25,8 +25,9 @@ use crate::{ | |||
25 | path::{ImportAlias, ModPath, PathKind}, | 25 | path::{ImportAlias, ModPath, PathKind}, |
26 | per_ns::PerNs, | 26 | per_ns::PerNs, |
27 | visibility::Visibility, | 27 | visibility::Visibility, |
28 | AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, | 28 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, |
29 | LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 29 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, |
30 | TraitLoc, TypeAliasLoc, UnionLoc, | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { | 33 | pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { |
@@ -99,11 +100,16 @@ struct ImportDirective { | |||
99 | #[derive(Clone, Debug, Eq, PartialEq)] | 100 | #[derive(Clone, Debug, Eq, PartialEq)] |
100 | struct MacroDirective { | 101 | struct MacroDirective { |
101 | module_id: LocalModuleId, | 102 | module_id: LocalModuleId, |
102 | ast_id: AstId<ast::MacroCall>, | 103 | ast_id: AstIdWithPath<ast::MacroCall>, |
103 | path: ModPath, | ||
104 | legacy: Option<MacroCallId>, | 104 | legacy: Option<MacroCallId>, |
105 | } | 105 | } |
106 | 106 | ||
107 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
108 | struct DeriveDirective { | ||
109 | module_id: LocalModuleId, | ||
110 | ast_id: AstIdWithPath<ast::ModuleItem>, | ||
111 | } | ||
112 | |||
107 | /// Walks the tree of module recursively | 113 | /// Walks the tree of module recursively |
108 | struct DefCollector<'a, DB> { | 114 | struct DefCollector<'a, DB> { |
109 | db: &'a DB, | 115 | db: &'a DB, |
@@ -112,7 +118,7 @@ struct DefCollector<'a, DB> { | |||
112 | unresolved_imports: Vec<ImportDirective>, | 118 | unresolved_imports: Vec<ImportDirective>, |
113 | resolved_imports: Vec<ImportDirective>, | 119 | resolved_imports: Vec<ImportDirective>, |
114 | unexpanded_macros: Vec<MacroDirective>, | 120 | unexpanded_macros: Vec<MacroDirective>, |
115 | unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, ModPath)>, | 121 | unexpanded_attribute_macros: Vec<DeriveDirective>, |
116 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, | 122 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, |
117 | cfg_options: &'a CfgOptions, | 123 | cfg_options: &'a CfgOptions, |
118 | } | 124 | } |
@@ -146,7 +152,7 @@ where | |||
146 | ReachedFixedPoint::Yes => break, | 152 | ReachedFixedPoint::Yes => break, |
147 | ReachedFixedPoint::No => i += 1, | 153 | ReachedFixedPoint::No => i += 1, |
148 | } | 154 | } |
149 | if i == 1000 { | 155 | if i == 10000 { |
150 | log::error!("name resolution is stuck"); | 156 | log::error!("name resolution is stuck"); |
151 | break; | 157 | break; |
152 | } | 158 | } |
@@ -515,16 +521,16 @@ where | |||
515 | return false; | 521 | return false; |
516 | } | 522 | } |
517 | 523 | ||
518 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 524 | if let Some(call_id) = directive.ast_id.as_call_id(self.db, |path| { |
519 | self.db, | 525 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
520 | ResolveMode::Other, | 526 | self.db, |
521 | directive.module_id, | 527 | ResolveMode::Other, |
522 | &directive.path, | 528 | directive.module_id, |
523 | BuiltinShadowMode::Module, | 529 | &path, |
524 | ); | 530 | BuiltinShadowMode::Module, |
525 | 531 | ); | |
526 | if let Some(def) = resolved_res.resolved_def.take_macros() { | 532 | resolved_res.resolved_def.take_macros() |
527 | let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id)); | 533 | }) { |
528 | resolved.push((directive.module_id, call_id)); | 534 | resolved.push((directive.module_id, call_id)); |
529 | res = ReachedFixedPoint::No; | 535 | res = ReachedFixedPoint::No; |
530 | return false; | 536 | return false; |
@@ -532,12 +538,11 @@ where | |||
532 | 538 | ||
533 | true | 539 | true |
534 | }); | 540 | }); |
535 | attribute_macros.retain(|(module_id, ast_id, path)| { | 541 | attribute_macros.retain(|directive| { |
536 | let resolved_res = self.resolve_attribute_macro(path); | 542 | if let Some(call_id) = |
537 | 543 | directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path)) | |
538 | if let Some(def) = resolved_res { | 544 | { |
539 | let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id)); | 545 | resolved.push((directive.module_id, call_id)); |
540 | resolved.push((*module_id, call_id)); | ||
541 | res = ReachedFixedPoint::No; | 546 | res = ReachedFixedPoint::No; |
542 | return false; | 547 | return false; |
543 | } | 548 | } |
@@ -833,20 +838,22 @@ where | |||
833 | }; | 838 | }; |
834 | let path = ModPath::from_tt_ident(ident); | 839 | let path = ModPath::from_tt_ident(ident); |
835 | 840 | ||
836 | let ast_id = AstId::new(self.file_id, def.kind.ast_id()); | 841 | let ast_id = AstIdWithPath::new(self.file_id, def.kind.ast_id(), path); |
837 | self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path)); | 842 | self.def_collector |
843 | .unexpanded_attribute_macros | ||
844 | .push(DeriveDirective { module_id: self.module_id, ast_id }); | ||
838 | } | 845 | } |
839 | } | 846 | } |
840 | } | 847 | } |
841 | 848 | ||
842 | fn collect_macro(&mut self, mac: &raw::MacroData) { | 849 | fn collect_macro(&mut self, mac: &raw::MacroData) { |
843 | let ast_id = AstId::new(self.file_id, mac.ast_id); | 850 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
844 | 851 | ||
845 | // Case 0: builtin macros | 852 | // Case 0: builtin macros |
846 | if mac.builtin { | 853 | if mac.builtin { |
847 | if let Some(name) = &mac.name { | 854 | if let Some(name) = &mac.name { |
848 | let krate = self.def_collector.def_map.krate; | 855 | let krate = self.def_collector.def_map.krate; |
849 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) { | 856 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) { |
850 | self.def_collector.define_macro( | 857 | self.def_collector.define_macro( |
851 | self.module_id, | 858 | self.module_id, |
852 | name.clone(), | 859 | name.clone(), |
@@ -862,7 +869,7 @@ where | |||
862 | if is_macro_rules(&mac.path) { | 869 | if is_macro_rules(&mac.path) { |
863 | if let Some(name) = &mac.name { | 870 | if let Some(name) = &mac.name { |
864 | let macro_id = MacroDefId { | 871 | let macro_id = MacroDefId { |
865 | ast_id: Some(ast_id), | 872 | ast_id: Some(ast_id.ast_id), |
866 | krate: Some(self.def_collector.def_map.krate), | 873 | krate: Some(self.def_collector.def_map.krate), |
867 | kind: MacroDefKind::Declarative, | 874 | kind: MacroDefKind::Declarative, |
868 | }; | 875 | }; |
@@ -872,15 +879,13 @@ where | |||
872 | } | 879 | } |
873 | 880 | ||
874 | // Case 2: try to resolve in legacy scope and expand macro_rules | 881 | // Case 2: try to resolve in legacy scope and expand macro_rules |
875 | if let Some(macro_def) = mac.path.as_ident().and_then(|name| { | 882 | if let Some(macro_call_id) = ast_id.as_call_id(self.def_collector.db, |path| { |
876 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) | 883 | path.as_ident().and_then(|name| { |
884 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) | ||
885 | }) | ||
877 | }) { | 886 | }) { |
878 | let macro_call_id = | ||
879 | macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id)); | ||
880 | |||
881 | self.def_collector.unexpanded_macros.push(MacroDirective { | 887 | self.def_collector.unexpanded_macros.push(MacroDirective { |
882 | module_id: self.module_id, | 888 | module_id: self.module_id, |
883 | path: mac.path.clone(), | ||
884 | ast_id, | 889 | ast_id, |
885 | legacy: Some(macro_call_id), | 890 | legacy: Some(macro_call_id), |
886 | }); | 891 | }); |
@@ -890,14 +895,12 @@ where | |||
890 | 895 | ||
891 | // Case 3: resolve in module scope, expand during name resolution. | 896 | // Case 3: resolve in module scope, expand during name resolution. |
892 | // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. | 897 | // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. |
893 | let mut path = mac.path.clone(); | 898 | if ast_id.path.is_ident() { |
894 | if path.is_ident() { | 899 | ast_id.path.kind = PathKind::Super(0); |
895 | path.kind = PathKind::Super(0); | ||
896 | } | 900 | } |
897 | 901 | ||
898 | self.def_collector.unexpanded_macros.push(MacroDirective { | 902 | self.def_collector.unexpanded_macros.push(MacroDirective { |
899 | module_id: self.module_id, | 903 | module_id: self.module_id, |
900 | path, | ||
901 | ast_id, | 904 | ast_id, |
902 | legacy: None, | 905 | legacy: None, |
903 | }); | 906 | }); |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 05cf4646a..e2b228e80 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -542,11 +542,7 @@ impl Resolver { | |||
542 | 542 | ||
543 | fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { | 543 | fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { |
544 | let params = db.generic_params(def); | 544 | let params = db.generic_params(def); |
545 | if params.types.is_empty() { | 545 | self.push_scope(Scope::GenericParams { def, params }) |
546 | self | ||
547 | } else { | ||
548 | self.push_scope(Scope::GenericParams { def, params }) | ||
549 | } | ||
550 | } | 546 | } |
551 | 547 | ||
552 | fn push_impl_block_scope(self, impl_block: ImplId) -> Resolver { | 548 | fn push_impl_block_scope(self, impl_block: ImplId) -> Resolver { |