diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-19 14:01:30 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-04-19 14:01:30 +0100 |
commit | e4f7f1e1bd2ca3c1816abf87779ad8893b7bf990 (patch) | |
tree | e843f284eca0c2a8d371c7af7c6532bace0d504d /crates/hir_def/src | |
parent | 3f1a220f32220cd4a664ca1adac5eb36e9eb33b2 (diff) | |
parent | f0507ab7c697ba4bcd59dd2f673dfff5072e3e1a (diff) |
Merge #8462
8462: Expand macros at type position r=jonas-schievink a=cynecx
Co-authored-by: cynecx <[email protected]>
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/body.rs | 26 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 34 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 5 | ||||
-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 | 18 |
7 files changed, 72 insertions, 36 deletions
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 96b959967..131f424cc 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -21,7 +21,7 @@ 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}; |
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}, |
@@ -37,13 +37,15 @@ use crate::{ | |||
37 | 37 | ||
38 | /// A subset of Expander that only deals with cfg attributes. We only need it to | 38 | /// A subset of Expander that only deals with cfg attributes. We only need it to |
39 | /// avoid cyclic queries in crate def map during enum processing. | 39 | /// avoid cyclic queries in crate def map during enum processing. |
40 | #[derive(Debug)] | ||
40 | pub(crate) struct CfgExpander { | 41 | pub(crate) struct CfgExpander { |
41 | cfg_options: CfgOptions, | 42 | cfg_options: CfgOptions, |
42 | hygiene: Hygiene, | 43 | hygiene: Hygiene, |
43 | krate: CrateId, | 44 | krate: CrateId, |
44 | } | 45 | } |
45 | 46 | ||
46 | pub(crate) struct Expander { | 47 | #[derive(Debug)] |
48 | pub struct Expander { | ||
47 | cfg_expander: CfgExpander, | 49 | cfg_expander: CfgExpander, |
48 | def_map: Arc<DefMap>, | 50 | def_map: Arc<DefMap>, |
49 | current_file_id: HirFileId, | 51 | current_file_id: HirFileId, |
@@ -80,11 +82,7 @@ impl CfgExpander { | |||
80 | } | 82 | } |
81 | 83 | ||
82 | impl Expander { | 84 | impl Expander { |
83 | pub(crate) fn new( | 85 | pub fn new(db: &dyn DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { |
84 | db: &dyn DefDatabase, | ||
85 | current_file_id: HirFileId, | ||
86 | module: ModuleId, | ||
87 | ) -> Expander { | ||
88 | let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); | 86 | let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); |
89 | let def_map = module.def_map(db); | 87 | let def_map = module.def_map(db); |
90 | let ast_id_map = db.ast_id_map(current_file_id); | 88 | let ast_id_map = db.ast_id_map(current_file_id); |
@@ -98,7 +96,7 @@ impl Expander { | |||
98 | } | 96 | } |
99 | } | 97 | } |
100 | 98 | ||
101 | pub(crate) fn enter_expand<T: ast::AstNode>( | 99 | pub fn enter_expand<T: ast::AstNode>( |
102 | &mut self, | 100 | &mut self, |
103 | db: &dyn DefDatabase, | 101 | db: &dyn DefDatabase, |
104 | macro_call: ast::MacroCall, | 102 | macro_call: ast::MacroCall, |
@@ -170,7 +168,7 @@ impl Expander { | |||
170 | Ok(ExpandResult { value: Some((mark, node)), err }) | 168 | Ok(ExpandResult { value: Some((mark, node)), err }) |
171 | } | 169 | } |
172 | 170 | ||
173 | pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { | 171 | pub fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { |
174 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id); | 172 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id); |
175 | self.current_file_id = mark.file_id; | 173 | self.current_file_id = mark.file_id; |
176 | self.ast_id_map = mem::take(&mut mark.ast_id_map); | 174 | self.ast_id_map = mem::take(&mut mark.ast_id_map); |
@@ -190,8 +188,13 @@ impl Expander { | |||
190 | &self.cfg_expander.cfg_options | 188 | &self.cfg_expander.cfg_options |
191 | } | 189 | } |
192 | 190 | ||
191 | pub fn current_file_id(&self) -> HirFileId { | ||
192 | self.current_file_id | ||
193 | } | ||
194 | |||
193 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { | 195 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { |
194 | Path::from_src(path, &self.cfg_expander.hygiene) | 196 | let ctx = LowerCtx::with_hygiene(&self.cfg_expander.hygiene); |
197 | Path::from_src(path, &ctx) | ||
195 | } | 198 | } |
196 | 199 | ||
197 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { | 200 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { |
@@ -204,7 +207,8 @@ impl Expander { | |||
204 | } | 207 | } |
205 | } | 208 | } |
206 | 209 | ||
207 | pub(crate) struct Mark { | 210 | #[derive(Debug)] |
211 | pub struct Mark { | ||
208 | file_id: HirFileId, | 212 | file_id: HirFileId, |
209 | ast_id_map: Arc<AstIdMap>, | 213 | ast_id_map: Arc<AstIdMap>, |
210 | bomb: DropBomb, | 214 | bomb: DropBomb, |
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/item_tree.rs b/crates/hir_def/src/item_tree.rs index 94e08f835..16a94a058 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -104,6 +104,11 @@ impl ItemTree { | |||
104 | // items and expanded during block DefMap computation | 104 | // items and expanded during block DefMap computation |
105 | return Default::default(); | 105 | return Default::default(); |
106 | }, | 106 | }, |
107 | ast::Type(ty) => { | ||
108 | // Types can contain inner items. We return an empty item tree in this case, but | ||
109 | // still need to collect inner items. | ||
110 | ctx.lower_inner_items(ty.syntax()) | ||
111 | }, | ||
107 | ast::Expr(e) => { | 112 | ast::Expr(e) => { |
108 | // Macros can expand to expressions. We return an empty item tree in this case, but | 113 | // Macros can expand to expressions. We return an empty item tree in this case, but |
109 | // still need to collect inner items. | 114 | // still need to collect inner items. |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 5ac1670b5..25694f037 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -688,6 +688,7 @@ impl<T: ast::AstNode> AstIdWithPath<T> { | |||
688 | } | 688 | } |
689 | } | 689 | } |
690 | 690 | ||
691 | #[derive(Debug)] | ||
691 | pub struct UnresolvedMacro { | 692 | pub struct UnresolvedMacro { |
692 | pub path: ModPath, | 693 | pub path: ModPath, |
693 | } | 694 | } |
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..ea29da5da 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -1,6 +1,7 @@ | |||
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 | |
4 | use hir_expand::{name::Name, AstId, InFile}; | ||
4 | use syntax::ast; | 5 | use syntax::ast; |
5 | 6 | ||
6 | use crate::{body::LowerCtx, path::Path}; | 7 | use crate::{body::LowerCtx, path::Path}; |
@@ -68,6 +69,7 @@ impl TraitRef { | |||
68 | } | 69 | } |
69 | } | 70 | } |
70 | } | 71 | } |
72 | |||
71 | /// Compare ty::Ty | 73 | /// Compare ty::Ty |
72 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 74 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
73 | pub enum TypeRef { | 75 | pub enum TypeRef { |
@@ -84,6 +86,7 @@ pub enum TypeRef { | |||
84 | // For | 86 | // For |
85 | ImplTrait(Vec<TypeBound>), | 87 | ImplTrait(Vec<TypeBound>), |
86 | DynTrait(Vec<TypeBound>), | 88 | DynTrait(Vec<TypeBound>), |
89 | Macro(AstId<ast::MacroCall>), | ||
87 | Error, | 90 | Error, |
88 | } | 91 | } |
89 | 92 | ||
@@ -116,7 +119,7 @@ pub enum TypeBound { | |||
116 | 119 | ||
117 | impl TypeRef { | 120 | impl TypeRef { |
118 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. | 121 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. |
119 | pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Self { | 122 | pub fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Self { |
120 | match node { | 123 | match node { |
121 | ast::Type::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()), | 124 | ast::Type::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()), |
122 | ast::Type::TupleType(inner) => { | 125 | ast::Type::TupleType(inner) => { |
@@ -176,8 +179,13 @@ impl TypeRef { | |||
176 | ast::Type::DynTraitType(inner) => { | 179 | ast::Type::DynTraitType(inner) => { |
177 | TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) | 180 | TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) |
178 | } | 181 | } |
179 | // FIXME: Macros in type position are not yet supported. | 182 | ast::Type::MacroType(mt) => match mt.macro_call() { |
180 | ast::Type::MacroType(_) => TypeRef::Error, | 183 | Some(mc) => ctx |
184 | .ast_id(&mc) | ||
185 | .map(|mc| TypeRef::Macro(InFile::new(ctx.file_id(), mc))) | ||
186 | .unwrap_or(TypeRef::Error), | ||
187 | None => TypeRef::Error, | ||
188 | }, | ||
181 | } | 189 | } |
182 | } | 190 | } |
183 | 191 | ||
@@ -215,7 +223,7 @@ impl TypeRef { | |||
215 | } | 223 | } |
216 | } | 224 | } |
217 | TypeRef::Path(path) => go_path(path, f), | 225 | TypeRef::Path(path) => go_path(path, f), |
218 | TypeRef::Never | TypeRef::Placeholder | TypeRef::Error => {} | 226 | TypeRef::Never | TypeRef::Placeholder | TypeRef::Macro(_) | TypeRef::Error => {} |
219 | }; | 227 | }; |
220 | } | 228 | } |
221 | 229 | ||