diff options
author | cynecx <[email protected]> | 2021-04-10 16:49:12 +0100 |
---|---|---|
committer | cynecx <[email protected]> | 2021-04-17 15:24:56 +0100 |
commit | cf3b4f1e208247c9d171273dabff9c6b3c98a240 (patch) | |
tree | 0cae2703b98ba8640ce6693abe32fb51fe27fdda /crates | |
parent | fb2d284f28f70426e39e1b92d95bdbb217a48109 (diff) |
hir_ty: Expand macros at type position
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/semantics.rs | 4 | ||||
-rw-r--r-- | crates/hir/src/source_analyzer.rs | 9 | ||||
-rw-r--r-- | crates/hir_def/src/body.rs | 74 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 34 | ||||
-rw-r--r-- | crates/hir_def/src/data.rs | 8 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 16 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 7 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 17 | ||||
-rw-r--r-- | crates/hir_def/src/type_ref.rs | 102 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 1 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 1 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 12 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 169 | ||||
-rw-r--r-- | crates/parser/src/grammar/types.rs | 10 | ||||
-rw-r--r-- | crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast | 48 |
17 files changed, 434 insertions, 81 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 7955bf0b5..29c0821cf 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -6,6 +6,7 @@ use std::{cell::RefCell, fmt, iter::successors}; | |||
6 | 6 | ||
7 | use base_db::{FileId, FileRange}; | 7 | use base_db::{FileId, FileRange}; |
8 | use hir_def::{ | 8 | use hir_def::{ |
9 | body, | ||
9 | resolver::{self, HasResolver, Resolver, TypeNs}, | 10 | resolver::{self, HasResolver, Resolver, TypeNs}, |
10 | AsMacroCall, FunctionId, TraitId, VariantId, | 11 | AsMacroCall, FunctionId, TraitId, VariantId, |
11 | }; | 12 | }; |
@@ -854,7 +855,8 @@ impl<'a> SemanticsScope<'a> { | |||
854 | /// necessary a heuristic, as it doesn't take hygiene into account. | 855 | /// necessary a heuristic, as it doesn't take hygiene into account. |
855 | pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> { | 856 | pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> { |
856 | let hygiene = Hygiene::new(self.db.upcast(), self.file_id); | 857 | let hygiene = Hygiene::new(self.db.upcast(), self.file_id); |
857 | let path = Path::from_src(path.clone(), &hygiene)?; | 858 | let ctx = body::LowerCtx::with_hygiene(&hygiene); |
859 | let path = Path::from_src(path.clone(), &ctx)?; | ||
858 | resolve_hir_path(self.db, &self.resolver, &path) | 860 | resolve_hir_path(self.db, &self.resolver, &path) |
859 | } | 861 | } |
860 | } | 862 | } |
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 847d2537d..0895bd6f1 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs | |||
@@ -9,6 +9,7 @@ use std::{iter::once, sync::Arc}; | |||
9 | 9 | ||
10 | use hir_def::{ | 10 | use hir_def::{ |
11 | body::{ | 11 | body::{ |
12 | self, | ||
12 | scope::{ExprScopes, ScopeId}, | 13 | scope::{ExprScopes, ScopeId}, |
13 | Body, BodySourceMap, | 14 | Body, BodySourceMap, |
14 | }, | 15 | }, |
@@ -202,8 +203,8 @@ impl SourceAnalyzer { | |||
202 | db: &dyn HirDatabase, | 203 | db: &dyn HirDatabase, |
203 | macro_call: InFile<&ast::MacroCall>, | 204 | macro_call: InFile<&ast::MacroCall>, |
204 | ) -> Option<MacroDef> { | 205 | ) -> Option<MacroDef> { |
205 | let hygiene = Hygiene::new(db.upcast(), macro_call.file_id); | 206 | let ctx = body::LowerCtx::new(db.upcast(), macro_call.file_id); |
206 | let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &hygiene))?; | 207 | let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?; |
207 | self.resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(|it| it.into()) | 208 | self.resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(|it| it.into()) |
208 | } | 209 | } |
209 | 210 | ||
@@ -281,7 +282,9 @@ impl SourceAnalyzer { | |||
281 | } | 282 | } |
282 | 283 | ||
283 | // This must be a normal source file rather than macro file. | 284 | // This must be a normal source file rather than macro file. |
284 | let hir_path = Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; | 285 | let hygiene = Hygiene::new(db.upcast(), self.file_id); |
286 | let ctx = body::LowerCtx::with_hygiene(&hygiene); | ||
287 | let hir_path = Path::from_src(path.clone(), &ctx)?; | ||
285 | 288 | ||
286 | // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we | 289 | // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we |
287 | // trying to resolve foo::bar. | 290 | // trying to resolve foo::bar. |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 96b959967..44ae13643 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -19,9 +19,9 @@ use hir_expand::{ | |||
19 | use la_arena::{Arena, ArenaMap}; | 19 | use la_arena::{Arena, ArenaMap}; |
20 | use profile::Count; | 20 | use profile::Count; |
21 | use rustc_hash::FxHashMap; | 21 | use rustc_hash::FxHashMap; |
22 | use syntax::{ast, AstNode, AstPtr}; | 22 | use syntax::{ast, AstNode, AstPtr, SyntaxNode}; |
23 | 23 | ||
24 | pub(crate) use lower::LowerCtx; | 24 | pub use lower::LowerCtx; |
25 | 25 | ||
26 | use crate::{ | 26 | use crate::{ |
27 | attr::{Attrs, RawAttrs}, | 27 | attr::{Attrs, RawAttrs}, |
@@ -98,11 +98,14 @@ impl Expander { | |||
98 | } | 98 | } |
99 | } | 99 | } |
100 | 100 | ||
101 | pub(crate) fn enter_expand<T: ast::AstNode>( | 101 | fn enter_expand_intern( |
102 | &mut self, | 102 | &mut self, |
103 | db: &dyn DefDatabase, | 103 | db: &dyn DefDatabase, |
104 | macro_call: ast::MacroCall, | 104 | macro_call: ast::MacroCall, |
105 | ) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> { | 105 | ) -> Result< |
106 | ExpandResult<Option<(SyntaxNode, impl FnMut(&dyn DefDatabase) -> Mark + '_)>>, | ||
107 | UnresolvedMacro, | ||
108 | > { | ||
106 | if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT { | 109 | if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT { |
107 | cov_mark::hit!(your_stack_belongs_to_me); | 110 | cov_mark::hit!(your_stack_belongs_to_me); |
108 | return Ok(ExpandResult::str_err( | 111 | return Ok(ExpandResult::str_err( |
@@ -147,6 +150,55 @@ impl Expander { | |||
147 | } | 150 | } |
148 | }; | 151 | }; |
149 | 152 | ||
153 | let this = self; | ||
154 | |||
155 | let advance_state = move |db: &dyn DefDatabase| { | ||
156 | this.recursion_limit += 1; | ||
157 | let mark = Mark { | ||
158 | file_id: this.current_file_id, | ||
159 | ast_id_map: mem::take(&mut this.ast_id_map), | ||
160 | bomb: DropBomb::new("expansion mark dropped"), | ||
161 | }; | ||
162 | this.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); | ||
163 | this.current_file_id = file_id; | ||
164 | this.ast_id_map = db.ast_id_map(file_id); | ||
165 | mark | ||
166 | }; | ||
167 | |||
168 | Ok(ExpandResult { value: Some((raw_node, advance_state)), err }) | ||
169 | } | ||
170 | |||
171 | pub(crate) fn enter_expand_raw( | ||
172 | &mut self, | ||
173 | db: &dyn DefDatabase, | ||
174 | macro_call: ast::MacroCall, | ||
175 | ) -> Result<ExpandResult<Option<(Mark, SyntaxNode)>>, UnresolvedMacro> { | ||
176 | let (raw_node, mut advance_state, err) = match self.enter_expand_intern(db, macro_call)? { | ||
177 | ExpandResult { value: Some((raw_node, advance_state)), err } => { | ||
178 | (raw_node, advance_state, err) | ||
179 | } | ||
180 | ExpandResult { value: None, err } => return Ok(ExpandResult { value: None, err }), | ||
181 | }; | ||
182 | |||
183 | log::debug!("macro expansion {:#?}", raw_node); | ||
184 | |||
185 | let mark = advance_state(db); | ||
186 | |||
187 | Ok(ExpandResult { value: Some((mark, raw_node)), err }) | ||
188 | } | ||
189 | |||
190 | pub(crate) fn enter_expand<T: ast::AstNode>( | ||
191 | &mut self, | ||
192 | db: &dyn DefDatabase, | ||
193 | macro_call: ast::MacroCall, | ||
194 | ) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> { | ||
195 | let (raw_node, mut advance_state, err) = match self.enter_expand_intern(db, macro_call)? { | ||
196 | ExpandResult { value: Some((raw_node, advance_state)), err } => { | ||
197 | (raw_node, advance_state, err) | ||
198 | } | ||
199 | ExpandResult { value: None, err } => return Ok(ExpandResult { value: None, err }), | ||
200 | }; | ||
201 | |||
150 | let node = match T::cast(raw_node) { | 202 | let node = match T::cast(raw_node) { |
151 | Some(it) => it, | 203 | Some(it) => it, |
152 | None => { | 204 | None => { |
@@ -157,15 +209,7 @@ impl Expander { | |||
157 | 209 | ||
158 | log::debug!("macro expansion {:#?}", node.syntax()); | 210 | log::debug!("macro expansion {:#?}", node.syntax()); |
159 | 211 | ||
160 | self.recursion_limit += 1; | 212 | let mark = advance_state(db); |
161 | let mark = Mark { | ||
162 | file_id: self.current_file_id, | ||
163 | ast_id_map: mem::take(&mut self.ast_id_map), | ||
164 | bomb: DropBomb::new("expansion mark dropped"), | ||
165 | }; | ||
166 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); | ||
167 | self.current_file_id = file_id; | ||
168 | self.ast_id_map = db.ast_id_map(file_id); | ||
169 | 213 | ||
170 | Ok(ExpandResult { value: Some((mark, node)), err }) | 214 | Ok(ExpandResult { value: Some((mark, node)), err }) |
171 | } | 215 | } |
@@ -191,7 +235,8 @@ impl Expander { | |||
191 | } | 235 | } |
192 | 236 | ||
193 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { | 237 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { |
194 | Path::from_src(path, &self.cfg_expander.hygiene) | 238 | let ctx = LowerCtx::with_hygiene(&self.cfg_expander.hygiene); |
239 | Path::from_src(path, &ctx) | ||
195 | } | 240 | } |
196 | 241 | ||
197 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { | 242 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { |
@@ -204,6 +249,7 @@ impl Expander { | |||
204 | } | 249 | } |
205 | } | 250 | } |
206 | 251 | ||
252 | #[derive(Debug)] | ||
207 | pub(crate) struct Mark { | 253 | pub(crate) struct Mark { |
208 | file_id: HirFileId, | 254 | file_id: HirFileId, |
209 | ast_id_map: Arc<AstIdMap>, | 255 | ast_id_map: Arc<AstIdMap>, |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index c0b0b7841..c11da30d2 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` | 1 | //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` |
2 | //! representation. | 2 | //! representation. |
3 | 3 | ||
4 | use std::mem; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use either::Either; | 6 | use either::Either; |
7 | use hir_expand::{ | 7 | use hir_expand::{ |
8 | ast_id_map::{AstIdMap, FileAstId}, | ||
8 | hygiene::Hygiene, | 9 | hygiene::Hygiene, |
9 | name::{name, AsName, Name}, | 10 | name::{name, AsName, Name}, |
10 | ExpandError, HirFileId, | 11 | ExpandError, HirFileId, |
@@ -39,20 +40,39 @@ use crate::{ | |||
39 | 40 | ||
40 | use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; | 41 | use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; |
41 | 42 | ||
42 | pub(crate) struct LowerCtx { | 43 | pub struct LowerCtx { |
43 | hygiene: Hygiene, | 44 | hygiene: Hygiene, |
45 | file_id: Option<HirFileId>, | ||
46 | source_ast_id_map: Option<Arc<AstIdMap>>, | ||
44 | } | 47 | } |
45 | 48 | ||
46 | impl LowerCtx { | 49 | impl LowerCtx { |
47 | pub(crate) fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self { | 50 | pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self { |
48 | LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) } | 51 | LowerCtx { |
52 | hygiene: Hygiene::new(db.upcast(), file_id), | ||
53 | file_id: Some(file_id), | ||
54 | source_ast_id_map: Some(db.ast_id_map(file_id)), | ||
55 | } | ||
56 | } | ||
57 | |||
58 | pub fn with_hygiene(hygiene: &Hygiene) -> Self { | ||
59 | LowerCtx { hygiene: hygiene.clone(), file_id: None, source_ast_id_map: None } | ||
60 | } | ||
61 | |||
62 | pub(crate) fn hygiene(&self) -> &Hygiene { | ||
63 | &self.hygiene | ||
49 | } | 64 | } |
50 | pub(crate) fn with_hygiene(hygiene: &Hygiene) -> Self { | 65 | |
51 | LowerCtx { hygiene: hygiene.clone() } | 66 | pub(crate) fn file_id(&self) -> HirFileId { |
67 | self.file_id.unwrap() | ||
52 | } | 68 | } |
53 | 69 | ||
54 | pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> { | 70 | pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> { |
55 | Path::from_src(ast, &self.hygiene) | 71 | Path::from_src(ast, self) |
72 | } | ||
73 | |||
74 | pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> Option<FileAstId<N>> { | ||
75 | self.source_ast_id_map.as_ref().map(|ast_id_map| ast_id_map.ast_id(item)) | ||
56 | } | 76 | } |
57 | } | 77 | } |
58 | 78 | ||
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 135a6698e..8732b1e3e 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -123,10 +123,11 @@ impl TypeAliasData { | |||
123 | let loc = typ.lookup(db); | 123 | let loc = typ.lookup(db); |
124 | let item_tree = loc.id.item_tree(db); | 124 | let item_tree = loc.id.item_tree(db); |
125 | let typ = &item_tree[loc.id.value]; | 125 | let typ = &item_tree[loc.id.value]; |
126 | let type_ref = typ.type_ref.clone(); | ||
126 | 127 | ||
127 | Arc::new(TypeAliasData { | 128 | Arc::new(TypeAliasData { |
128 | name: typ.name.clone(), | 129 | name: typ.name.clone(), |
129 | type_ref: typ.type_ref.clone(), | 130 | type_ref: type_ref, |
130 | visibility: item_tree[typ.visibility].clone(), | 131 | visibility: item_tree[typ.visibility].clone(), |
131 | is_extern: typ.is_extern, | 132 | is_extern: typ.is_extern, |
132 | bounds: typ.bounds.to_vec(), | 133 | bounds: typ.bounds.to_vec(), |
@@ -202,12 +203,13 @@ impl ImplData { | |||
202 | let item_tree = impl_loc.id.item_tree(db); | 203 | let item_tree = impl_loc.id.item_tree(db); |
203 | let impl_def = &item_tree[impl_loc.id.value]; | 204 | let impl_def = &item_tree[impl_loc.id.value]; |
204 | let target_trait = impl_def.target_trait.clone(); | 205 | let target_trait = impl_def.target_trait.clone(); |
205 | let self_ty = impl_def.self_ty.clone(); | ||
206 | let is_negative = impl_def.is_negative; | 206 | let is_negative = impl_def.is_negative; |
207 | let module_id = impl_loc.container; | 207 | let module_id = impl_loc.container; |
208 | let container = AssocContainerId::ImplId(id); | 208 | let container = AssocContainerId::ImplId(id); |
209 | let mut expander = Expander::new(db, impl_loc.id.file_id(), module_id); | 209 | let file_id = impl_loc.id.file_id(); |
210 | let self_ty = impl_def.self_ty.clone(); | ||
210 | 211 | ||
212 | let mut expander = Expander::new(db, file_id, module_id); | ||
211 | let items = collect_items( | 213 | let items = collect_items( |
212 | db, | 214 | db, |
213 | module_id, | 215 | module_id, |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 45b099cf3..2975786dd 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -189,12 +189,16 @@ impl Ctx { | |||
189 | block_stack.push(self.source_ast_id_map.ast_id(&block)); | 189 | block_stack.push(self.source_ast_id_map.ast_id(&block)); |
190 | }, | 190 | }, |
191 | ast::Item(item) => { | 191 | ast::Item(item) => { |
192 | // FIXME: This triggers for macro calls in expression/pattern/type position | 192 | // FIXME: This triggers for macro calls in expression/pattern |
193 | let mod_items = self.lower_mod_item(&item, true); | 193 | if let Some(SyntaxKind::MACRO_TYPE) = node.parent().map(|p| p.kind()) { |
194 | let current_block = block_stack.last(); | 194 | // Ignore macros at type position |
195 | if let (Some(mod_items), Some(block)) = (mod_items, current_block) { | 195 | } else { |
196 | if !mod_items.0.is_empty() { | 196 | let mod_items = self.lower_mod_item(&item, true); |
197 | self.data().inner_items.entry(*block).or_default().extend(mod_items.0.iter().copied()); | 197 | let current_block = block_stack.last(); |
198 | if let (Some(mod_items), Some(block)) = (mod_items, current_block) { | ||
199 | if !mod_items.0.is_empty() { | ||
200 | self.data().inner_items.entry(*block).or_default().extend(mod_items.0.iter().copied()); | ||
201 | } | ||
198 | } | 202 | } |
199 | } | 203 | } |
200 | }, | 204 | }, |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 000567d99..059724daa 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -676,6 +676,7 @@ impl<T: ast::AstNode> AstIdWithPath<T> { | |||
676 | } | 676 | } |
677 | } | 677 | } |
678 | 678 | ||
679 | #[derive(Debug)] | ||
679 | pub struct UnresolvedMacro { | 680 | pub struct UnresolvedMacro { |
680 | pub path: ModPath, | 681 | pub path: ModPath, |
681 | } | 682 | } |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index b528ff8ba..509f77850 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -48,7 +48,8 @@ pub enum ImportAlias { | |||
48 | 48 | ||
49 | impl ModPath { | 49 | impl ModPath { |
50 | pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> { | 50 | pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> { |
51 | lower::lower_path(path, hygiene).map(|it| (*it.mod_path).clone()) | 51 | let ctx = LowerCtx::with_hygiene(hygiene); |
52 | lower::lower_path(path, &ctx).map(|it| (*it.mod_path).clone()) | ||
52 | } | 53 | } |
53 | 54 | ||
54 | pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath { | 55 | pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath { |
@@ -167,8 +168,8 @@ pub enum GenericArg { | |||
167 | impl Path { | 168 | impl Path { |
168 | /// Converts an `ast::Path` to `Path`. Works with use trees. | 169 | /// Converts an `ast::Path` to `Path`. Works with use trees. |
169 | /// It correctly handles `$crate` based path from macro call. | 170 | /// It correctly handles `$crate` based path from macro call. |
170 | pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<Path> { | 171 | pub fn from_src(path: ast::Path, ctx: &LowerCtx) -> Option<Path> { |
171 | lower::lower_path(path, hygiene) | 172 | lower::lower_path(path, ctx) |
172 | } | 173 | } |
173 | 174 | ||
174 | /// Converts a known mod path to `Path`. | 175 | /// Converts a known mod path to `Path`. |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 7b29d9d4f..1df6db525 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -6,10 +6,7 @@ use crate::intern::Interned; | |||
6 | use std::sync::Arc; | 6 | use std::sync::Arc; |
7 | 7 | ||
8 | use either::Either; | 8 | use either::Either; |
9 | use hir_expand::{ | 9 | use hir_expand::name::{name, AsName}; |
10 | hygiene::Hygiene, | ||
11 | name::{name, AsName}, | ||
12 | }; | ||
13 | use syntax::ast::{self, AstNode, TypeBoundsOwner}; | 10 | use syntax::ast::{self, AstNode, TypeBoundsOwner}; |
14 | 11 | ||
15 | use super::AssociatedTypeBinding; | 12 | use super::AssociatedTypeBinding; |
@@ -23,12 +20,12 @@ pub(super) use lower_use::lower_use_tree; | |||
23 | 20 | ||
24 | /// Converts an `ast::Path` to `Path`. Works with use trees. | 21 | /// Converts an `ast::Path` to `Path`. Works with use trees. |
25 | /// It correctly handles `$crate` based path from macro call. | 22 | /// It correctly handles `$crate` based path from macro call. |
26 | pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { | 23 | pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<Path> { |
27 | let mut kind = PathKind::Plain; | 24 | let mut kind = PathKind::Plain; |
28 | let mut type_anchor = None; | 25 | let mut type_anchor = None; |
29 | let mut segments = Vec::new(); | 26 | let mut segments = Vec::new(); |
30 | let mut generic_args = Vec::new(); | 27 | let mut generic_args = Vec::new(); |
31 | let ctx = LowerCtx::with_hygiene(hygiene); | 28 | let hygiene = ctx.hygiene(); |
32 | loop { | 29 | loop { |
33 | let segment = path.segment()?; | 30 | let segment = path.segment()?; |
34 | 31 | ||
@@ -43,10 +40,10 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
43 | Either::Left(name) => { | 40 | Either::Left(name) => { |
44 | let args = segment | 41 | let args = segment |
45 | .generic_arg_list() | 42 | .generic_arg_list() |
46 | .and_then(|it| lower_generic_args(&ctx, it)) | 43 | .and_then(|it| lower_generic_args(ctx, it)) |
47 | .or_else(|| { | 44 | .or_else(|| { |
48 | lower_generic_args_from_fn_path( | 45 | lower_generic_args_from_fn_path( |
49 | &ctx, | 46 | ctx, |
50 | segment.param_list(), | 47 | segment.param_list(), |
51 | segment.ret_type(), | 48 | segment.ret_type(), |
52 | ) | 49 | ) |
@@ -64,7 +61,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
64 | ast::PathSegmentKind::Type { type_ref, trait_ref } => { | 61 | ast::PathSegmentKind::Type { type_ref, trait_ref } => { |
65 | assert!(path.qualifier().is_none()); // this can only occur at the first segment | 62 | assert!(path.qualifier().is_none()); // this can only occur at the first segment |
66 | 63 | ||
67 | let self_type = TypeRef::from_ast(&ctx, type_ref?); | 64 | let self_type = TypeRef::from_ast(ctx, type_ref?); |
68 | 65 | ||
69 | match trait_ref { | 66 | match trait_ref { |
70 | // <T>::foo | 67 | // <T>::foo |
@@ -74,7 +71,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
74 | } | 71 | } |
75 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo | 72 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo |
76 | Some(trait_ref) => { | 73 | Some(trait_ref) => { |
77 | let path = Path::from_src(trait_ref.path()?, hygiene)?; | 74 | let path = Path::from_src(trait_ref.path()?, ctx)?; |
78 | let mod_path = (*path.mod_path).clone(); | 75 | let mod_path = (*path.mod_path).clone(); |
79 | let num_segments = path.mod_path.segments.len(); | 76 | let num_segments = path.mod_path.segments.len(); |
80 | kind = mod_path.kind; | 77 | kind = mod_path.kind; |
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index 4c24aae94..0832371c0 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -1,9 +1,16 @@ | |||
1 | //! HIR for references to types. Paths in these are not yet resolved. They can | 1 | //! HIR for references to types. Paths in these are not yet resolved. They can |
2 | //! be directly created from an ast::TypeRef, without further queries. | 2 | //! be directly created from an ast::TypeRef, without further queries. |
3 | use hir_expand::name::Name; | 3 | use std::borrow::Cow; |
4 | use syntax::ast; | ||
5 | 4 | ||
6 | use crate::{body::LowerCtx, path::Path}; | 5 | use hir_expand::{ast_id_map::FileAstId, name::Name, ExpandResult, InFile}; |
6 | use syntax::{algo::SyntaxRewriter, ast, AstNode, SyntaxKind, SyntaxNode}; | ||
7 | |||
8 | use crate::{ | ||
9 | body::{Expander, LowerCtx}, | ||
10 | db::DefDatabase, | ||
11 | path::Path, | ||
12 | ModuleId, | ||
13 | }; | ||
7 | 14 | ||
8 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | 15 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
9 | pub enum Mutability { | 16 | pub enum Mutability { |
@@ -68,6 +75,7 @@ impl TraitRef { | |||
68 | } | 75 | } |
69 | } | 76 | } |
70 | } | 77 | } |
78 | |||
71 | /// Compare ty::Ty | 79 | /// Compare ty::Ty |
72 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 80 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
73 | pub enum TypeRef { | 81 | pub enum TypeRef { |
@@ -84,6 +92,7 @@ pub enum TypeRef { | |||
84 | // For | 92 | // For |
85 | ImplTrait(Vec<TypeBound>), | 93 | ImplTrait(Vec<TypeBound>), |
86 | DynTrait(Vec<TypeBound>), | 94 | DynTrait(Vec<TypeBound>), |
95 | Macro(InFile<FileAstId<ast::MacroCall>>), | ||
87 | Error, | 96 | Error, |
88 | } | 97 | } |
89 | 98 | ||
@@ -176,8 +185,13 @@ impl TypeRef { | |||
176 | ast::Type::DynTraitType(inner) => { | 185 | ast::Type::DynTraitType(inner) => { |
177 | TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) | 186 | TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) |
178 | } | 187 | } |
179 | // FIXME: Macros in type position are not yet supported. | 188 | ast::Type::MacroType(mt) => match mt.macro_call() { |
180 | ast::Type::MacroType(_) => TypeRef::Error, | 189 | Some(mc) => ctx |
190 | .ast_id(&mc) | ||
191 | .map(|mc| TypeRef::Macro(InFile::new(ctx.file_id(), mc))) | ||
192 | .unwrap_or(TypeRef::Error), | ||
193 | None => TypeRef::Error, | ||
194 | }, | ||
181 | } | 195 | } |
182 | } | 196 | } |
183 | 197 | ||
@@ -193,6 +207,16 @@ impl TypeRef { | |||
193 | TypeRef::Tuple(Vec::new()) | 207 | TypeRef::Tuple(Vec::new()) |
194 | } | 208 | } |
195 | 209 | ||
210 | pub fn has_macro_calls(&self) -> bool { | ||
211 | let mut has_macro_call = false; | ||
212 | self.walk(&mut |ty_ref| { | ||
213 | if let TypeRef::Macro(_) = ty_ref { | ||
214 | has_macro_call |= true | ||
215 | } | ||
216 | }); | ||
217 | has_macro_call | ||
218 | } | ||
219 | |||
196 | pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) { | 220 | pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) { |
197 | go(self, f); | 221 | go(self, f); |
198 | 222 | ||
@@ -215,7 +239,7 @@ impl TypeRef { | |||
215 | } | 239 | } |
216 | } | 240 | } |
217 | TypeRef::Path(path) => go_path(path, f), | 241 | TypeRef::Path(path) => go_path(path, f), |
218 | TypeRef::Never | TypeRef::Placeholder | TypeRef::Error => {} | 242 | TypeRef::Never | TypeRef::Placeholder | TypeRef::Macro(_) | TypeRef::Error => {} |
219 | }; | 243 | }; |
220 | } | 244 | } |
221 | 245 | ||
@@ -290,3 +314,69 @@ impl TypeBound { | |||
290 | } | 314 | } |
291 | } | 315 | } |
292 | } | 316 | } |
317 | |||
318 | pub fn expand_type_ref<'a>( | ||
319 | db: &dyn DefDatabase, | ||
320 | module_id: ModuleId, | ||
321 | type_ref: &'a TypeRef, | ||
322 | ) -> Option<Cow<'a, TypeRef>> { | ||
323 | let macro_call = match type_ref { | ||
324 | TypeRef::Macro(macro_call) => macro_call, | ||
325 | _ => return Some(Cow::Borrowed(type_ref)), | ||
326 | }; | ||
327 | |||
328 | let file_id = macro_call.file_id; | ||
329 | let macro_call = macro_call.to_node(db.upcast()); | ||
330 | |||
331 | let mut expander = Expander::new(db, file_id, module_id); | ||
332 | let expanded = expand(db, &mut expander, ¯o_call, true)?; | ||
333 | |||
334 | let node = ast::Type::cast(expanded)?; | ||
335 | |||
336 | let ctx = LowerCtx::new(db, file_id); | ||
337 | return Some(Cow::Owned(TypeRef::from_ast(&ctx, node))); | ||
338 | |||
339 | fn expand( | ||
340 | db: &dyn DefDatabase, | ||
341 | expander: &mut Expander, | ||
342 | macro_call: &ast::MacroCall, | ||
343 | expect_type: bool, | ||
344 | ) -> Option<SyntaxNode> { | ||
345 | let (mark, mut expanded) = match expander.enter_expand_raw(db, macro_call.clone()) { | ||
346 | Ok(ExpandResult { value: Some((mark, expanded)), .. }) => (mark, expanded), | ||
347 | _ => return None, | ||
348 | }; | ||
349 | |||
350 | if expect_type && !ast::Type::can_cast(expanded.kind()) { | ||
351 | expander.exit(db, mark); | ||
352 | return None; | ||
353 | } | ||
354 | |||
355 | if ast::MacroType::can_cast(expanded.kind()) { | ||
356 | expanded = expanded.first_child()?; // MACRO_CALL | ||
357 | } | ||
358 | |||
359 | let mut rewriter = SyntaxRewriter::default(); | ||
360 | |||
361 | let children = expanded.descendants().filter_map(ast::MacroCall::cast); | ||
362 | for child in children { | ||
363 | if let Some(new_node) = expand(db, expander, &child, false) { | ||
364 | if expanded == *child.syntax() { | ||
365 | expanded = new_node; | ||
366 | } else { | ||
367 | let parent = child.syntax().parent(); | ||
368 | let old_node = match &parent { | ||
369 | Some(node) if node.kind() == SyntaxKind::MACRO_TYPE => node, | ||
370 | _ => child.syntax(), | ||
371 | }; | ||
372 | rewriter.replace(old_node, &new_node) | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | |||
377 | expander.exit(db, mark); | ||
378 | |||
379 | let res = rewriter.rewrite(&expanded); | ||
380 | Some(res) | ||
381 | } | ||
382 | } | ||
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index ca705ee9d..1e4b0cc19 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -440,6 +440,7 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | |||
440 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, | 440 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, |
441 | MACRO_STMTS => FragmentKind::Statements, | 441 | MACRO_STMTS => FragmentKind::Statements, |
442 | MACRO_PAT => FragmentKind::Pattern, | 442 | MACRO_PAT => FragmentKind::Pattern, |
443 | MACRO_TYPE => FragmentKind::Type, | ||
443 | ITEM_LIST => FragmentKind::Items, | 444 | ITEM_LIST => FragmentKind::Items, |
444 | LET_STMT => { | 445 | LET_STMT => { |
445 | // FIXME: Handle LHS Pattern | 446 | // FIXME: Handle LHS Pattern |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index ef126e4ad..a5ac32d3c 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -31,6 +31,7 @@ use parser::FragmentKind; | |||
31 | use std::sync::Arc; | 31 | use std::sync::Arc; |
32 | use syntax::{algo::SyntaxRewriter, SyntaxNode}; | 32 | use syntax::{algo::SyntaxRewriter, SyntaxNode}; |
33 | 33 | ||
34 | #[derive(Debug)] | ||
34 | pub struct ErrorEmitted { | 35 | pub struct ErrorEmitted { |
35 | _private: (), | 36 | _private: (), |
36 | } | 37 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index e7c9dabc2..63bcb0640 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -997,7 +997,7 @@ impl HirDisplay for TypeRef { | |||
997 | write!(f, "dyn ")?; | 997 | write!(f, "dyn ")?; |
998 | f.write_joined(bounds, " + ")?; | 998 | f.write_joined(bounds, " + ")?; |
999 | } | 999 | } |
1000 | TypeRef::Error => write!(f, "{{error}}")?, | 1000 | TypeRef::Error | TypeRef::Macro(_) => write!(f, "{{error}}")?, |
1001 | } | 1001 | } |
1002 | Ok(()) | 1002 | Ok(()) |
1003 | } | 1003 | } |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index a035686bc..95ca5bdb0 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -15,7 +15,7 @@ use hir_def::{ | |||
15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, | 15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, |
16 | path::{GenericArg, Path, PathSegment, PathSegments}, | 16 | path::{GenericArg, Path, PathSegment, PathSegments}, |
17 | resolver::{HasResolver, Resolver, TypeNs}, | 17 | resolver::{HasResolver, Resolver, TypeNs}, |
18 | type_ref::{TraitRef as HirTraitRef, TypeBound, TypeRef}, | 18 | type_ref::{expand_type_ref, TraitRef as HirTraitRef, TypeBound, TypeRef}, |
19 | AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, | 19 | AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, |
20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, | 20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, |
21 | TypeAliasId, TypeParamId, UnionId, VariantId, | 21 | TypeAliasId, TypeParamId, UnionId, VariantId, |
@@ -287,6 +287,16 @@ impl<'a> TyLoweringContext<'a> { | |||
287 | } | 287 | } |
288 | } | 288 | } |
289 | } | 289 | } |
290 | mt @ TypeRef::Macro(_) => { | ||
291 | if let Some(module_id) = self.resolver.module() { | ||
292 | match expand_type_ref(self.db.upcast(), module_id, mt) { | ||
293 | Some(type_ref) => self.lower_ty(type_ref.as_ref()), | ||
294 | None => TyKind::Error.intern(&Interner), | ||
295 | } | ||
296 | } else { | ||
297 | TyKind::Error.intern(&Interner) | ||
298 | } | ||
299 | } | ||
290 | TypeRef::Error => TyKind::Error.intern(&Interner), | 300 | TypeRef::Error => TyKind::Error.intern(&Interner), |
291 | }; | 301 | }; |
292 | (ty, res) | 302 | (ty, res) |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index b8e373ed8..cbe05a5c1 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -1074,3 +1074,172 @@ fn macro_in_arm() { | |||
1074 | "#]], | 1074 | "#]], |
1075 | ); | 1075 | ); |
1076 | } | 1076 | } |
1077 | |||
1078 | #[test] | ||
1079 | fn macro_in_type_alias_position() { | ||
1080 | check_infer( | ||
1081 | r#" | ||
1082 | macro_rules! U32 { | ||
1083 | () => { u32 }; | ||
1084 | } | ||
1085 | |||
1086 | trait Foo { | ||
1087 | type Ty; | ||
1088 | } | ||
1089 | |||
1090 | impl<T> Foo for T { | ||
1091 | type Ty = U32!(); | ||
1092 | } | ||
1093 | |||
1094 | type TayTo = U32!(); | ||
1095 | |||
1096 | fn testy() { | ||
1097 | let a: <() as Foo>::Ty; | ||
1098 | let b: TayTo; | ||
1099 | } | ||
1100 | "#, | ||
1101 | expect![[r#" | ||
1102 | 147..196 '{ ...yTo; }': () | ||
1103 | 157..158 'a': u32 | ||
1104 | 185..186 'b': u32 | ||
1105 | "#]], | ||
1106 | ); | ||
1107 | } | ||
1108 | |||
1109 | #[test] | ||
1110 | fn nested_macro_in_type_alias_position() { | ||
1111 | check_infer( | ||
1112 | r#" | ||
1113 | macro_rules! U32Inner2 { | ||
1114 | () => { u32 }; | ||
1115 | } | ||
1116 | |||
1117 | macro_rules! U32Inner1 { | ||
1118 | () => { U32Inner2!() }; | ||
1119 | } | ||
1120 | |||
1121 | macro_rules! U32 { | ||
1122 | () => { U32Inner1!() }; | ||
1123 | } | ||
1124 | |||
1125 | trait Foo { | ||
1126 | type Ty; | ||
1127 | } | ||
1128 | |||
1129 | impl<T> Foo for T { | ||
1130 | type Ty = U32!(); | ||
1131 | } | ||
1132 | |||
1133 | type TayTo = U32!(); | ||
1134 | |||
1135 | fn testy() { | ||
1136 | let a: <() as Foo>::Ty; | ||
1137 | let b: TayTo; | ||
1138 | } | ||
1139 | "#, | ||
1140 | expect![[r#" | ||
1141 | 259..308 '{ ...yTo; }': () | ||
1142 | 269..270 'a': u32 | ||
1143 | 297..298 'b': u32 | ||
1144 | "#]], | ||
1145 | ); | ||
1146 | } | ||
1147 | |||
1148 | #[test] | ||
1149 | fn macros_in_type_alias_position_generics() { | ||
1150 | check_infer( | ||
1151 | r#" | ||
1152 | struct Foo<A, B>(A, B); | ||
1153 | |||
1154 | macro_rules! U32 { | ||
1155 | () => { u32 }; | ||
1156 | } | ||
1157 | |||
1158 | macro_rules! Bar { | ||
1159 | () => { Foo<U32!(), U32!()> }; | ||
1160 | } | ||
1161 | |||
1162 | trait Moo { | ||
1163 | type Ty; | ||
1164 | } | ||
1165 | |||
1166 | impl<T> Moo for T { | ||
1167 | type Ty = Bar!(); | ||
1168 | } | ||
1169 | |||
1170 | type TayTo = Bar!(); | ||
1171 | |||
1172 | fn main() { | ||
1173 | let a: <() as Moo>::Ty; | ||
1174 | let b: TayTo; | ||
1175 | } | ||
1176 | "#, | ||
1177 | expect![[r#" | ||
1178 | 228..277 '{ ...yTo; }': () | ||
1179 | 238..239 'a': Foo<u32, u32> | ||
1180 | 266..267 'b': Foo<u32, u32> | ||
1181 | "#]], | ||
1182 | ); | ||
1183 | } | ||
1184 | |||
1185 | #[test] | ||
1186 | fn macros_in_type_position() { | ||
1187 | check_infer( | ||
1188 | r#" | ||
1189 | struct Foo<A, B>(A, B); | ||
1190 | |||
1191 | macro_rules! U32 { | ||
1192 | () => { u32 }; | ||
1193 | } | ||
1194 | |||
1195 | macro_rules! Bar { | ||
1196 | () => { Foo<U32!(), U32!()> }; | ||
1197 | } | ||
1198 | |||
1199 | fn main() { | ||
1200 | let a: Bar!(); | ||
1201 | } | ||
1202 | "#, | ||
1203 | expect![[r#" | ||
1204 | 133..155 '{ ...!(); }': () | ||
1205 | 143..144 'a': Foo<u32, u32> | ||
1206 | "#]], | ||
1207 | ); | ||
1208 | } | ||
1209 | |||
1210 | #[test] | ||
1211 | fn macros_in_type_generics() { | ||
1212 | check_infer( | ||
1213 | r#" | ||
1214 | struct Foo<A, B>(A, B); | ||
1215 | |||
1216 | macro_rules! U32 { | ||
1217 | () => { u32 }; | ||
1218 | } | ||
1219 | |||
1220 | macro_rules! Bar { | ||
1221 | () => { Foo<U32!(), U32!()> }; | ||
1222 | } | ||
1223 | |||
1224 | trait Moo { | ||
1225 | type Ty; | ||
1226 | } | ||
1227 | |||
1228 | impl<T> Moo for T { | ||
1229 | type Ty = Foo<Bar!(), Bar!()>; | ||
1230 | } | ||
1231 | |||
1232 | type TayTo = Foo<Bar!(), U32!()>; | ||
1233 | |||
1234 | fn main() { | ||
1235 | let a: <() as Moo>::Ty; | ||
1236 | let b: TayTo; | ||
1237 | } | ||
1238 | "#, | ||
1239 | expect![[r#" | ||
1240 | 254..303 '{ ...yTo; }': () | ||
1241 | 264..265 'a': Foo<Foo<u32, u32>, Foo<u32, u32>> | ||
1242 | 292..293 'b': Foo<Foo<u32, u32>, u32> | ||
1243 | "#]], | ||
1244 | ); | ||
1245 | } | ||
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs index 94cbf7d85..6ae3e734f 100644 --- a/crates/parser/src/grammar/types.rs +++ b/crates/parser/src/grammar/types.rs | |||
@@ -283,17 +283,21 @@ pub(super) fn path_type(p: &mut Parser) { | |||
283 | // type B = crate::foo!(); | 283 | // type B = crate::foo!(); |
284 | fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) { | 284 | fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) { |
285 | assert!(paths::is_path_start(p)); | 285 | assert!(paths::is_path_start(p)); |
286 | let r = p.start(); | ||
286 | let m = p.start(); | 287 | let m = p.start(); |
288 | |||
287 | paths::type_path(p); | 289 | paths::type_path(p); |
288 | 290 | ||
289 | let kind = if p.at(T![!]) && !p.at(T![!=]) { | 291 | let kind = if p.at(T![!]) && !p.at(T![!=]) { |
290 | items::macro_call_after_excl(p); | 292 | items::macro_call_after_excl(p); |
291 | MACRO_CALL | 293 | m.complete(p, MACRO_CALL); |
294 | MACRO_TYPE | ||
292 | } else { | 295 | } else { |
296 | m.abandon(p); | ||
293 | PATH_TYPE | 297 | PATH_TYPE |
294 | }; | 298 | }; |
295 | 299 | ||
296 | let path = m.complete(p, kind); | 300 | let path = r.complete(p, kind); |
297 | 301 | ||
298 | if allow_bounds { | 302 | if allow_bounds { |
299 | opt_type_bounds_as_dyn_trait_type(p, path); | 303 | opt_type_bounds_as_dyn_trait_type(p, path); |
@@ -319,7 +323,7 @@ pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) { | |||
319 | fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) { | 323 | fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) { |
320 | assert!(matches!( | 324 | assert!(matches!( |
321 | type_marker.kind(), | 325 | type_marker.kind(), |
322 | SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_CALL | 326 | SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE |
323 | )); | 327 | )); |
324 | if !p.at(T![+]) { | 328 | if !p.at(T![+]) { |
325 | return; | 329 | return; |
diff --git a/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast b/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast index 3016a6574..1ff3f7656 100644 --- a/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast +++ b/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast | |||
@@ -7,15 +7,16 @@ [email protected] | |||
7 | [email protected] " " | 7 | [email protected] " " |
8 | [email protected] "=" | 8 | [email protected] "=" |
9 | [email protected] " " | 9 | [email protected] " " |
10 | [email protected] | 10 | [email protected] |
11 | [email protected] | 11 | [email protected] |
12 | [email protected] | 12 | [email protected] |
13 | [email protected] | 13 | [email protected] |
14 | [email protected] "foo" | 14 | [email protected] |
15 | [email protected] "!" | 15 | [email protected] "foo" |
16 | [email protected] | 16 | [email protected] "!" |
17 | [email protected] "(" | 17 | [email protected] |
18 | [email protected] ")" | 18 | [email protected] "(" |
19 | [email protected] ")" | ||
19 | [email protected] ";" | 20 | [email protected] ";" |
20 | [email protected] "\n" | 21 | [email protected] "\n" |
21 | [email protected] | 22 | [email protected] |
@@ -26,19 +27,20 @@ [email protected] | |||
26 | [email protected] " " | 27 | [email protected] " " |
27 | [email protected] "=" | 28 | [email protected] "=" |
28 | [email protected] " " | 29 | [email protected] " " |
29 | [email protected] | 30 | [email protected] |
30 | [email protected] | 31 | [email protected] |
31 | [email protected] | 32 | [email protected] |
32 | [email protected] | 33 | [email protected] |
33 | [email protected] | 34 | [email protected] |
34 | [email protected] "crate" | 35 | [email protected] |
35 | [email protected] "::" | 36 | [email protected] "crate" |
36 | [email protected] | 37 | [email protected] "::" |
37 | [email protected] | 38 | [email protected] |
38 | [email protected] "foo" | 39 | [email protected] |
39 | [email protected] "!" | 40 | [email protected] "foo" |
40 | [email protected] | 41 | [email protected] "!" |
41 | [email protected] "(" | 42 | [email protected] |
42 | [email protected] ")" | 43 | [email protected] "(" |
44 | [email protected] ")" | ||
43 | [email protected] ";" | 45 | [email protected] ";" |
44 | [email protected] "\n" | 46 | [email protected] "\n" |