aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/body.rs24
-rw-r--r--crates/hir_def/src/body/lower.rs108
-rw-r--r--crates/hir_def/src/expr.rs30
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs4
4 files changed, 107 insertions, 59 deletions
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 998b82601..d07004b9d 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -26,7 +26,7 @@ pub(crate) use lower::LowerCtx;
26use crate::{ 26use crate::{
27 attr::{Attrs, RawAttrs}, 27 attr::{Attrs, RawAttrs},
28 db::DefDatabase, 28 db::DefDatabase,
29 expr::{Expr, ExprId, Pat, PatId}, 29 expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
30 item_scope::BuiltinShadowMode, 30 item_scope::BuiltinShadowMode,
31 item_scope::ItemScope, 31 item_scope::ItemScope,
32 nameres::CrateDefMap, 32 nameres::CrateDefMap,
@@ -226,6 +226,7 @@ pub(crate) struct Mark {
226pub struct Body { 226pub struct Body {
227 pub exprs: Arena<Expr>, 227 pub exprs: Arena<Expr>,
228 pub pats: Arena<Pat>, 228 pub pats: Arena<Pat>,
229 pub labels: Arena<Label>,
229 /// The patterns for the function's parameters. While the parameter types are 230 /// The patterns for the function's parameters. While the parameter types are
230 /// part of the function signature, the patterns are not (they don't change 231 /// part of the function signature, the patterns are not (they don't change
231 /// the external type of the function). 232 /// the external type of the function).
@@ -244,6 +245,8 @@ pub type ExprSource = InFile<ExprPtr>;
244pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; 245pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
245pub type PatSource = InFile<PatPtr>; 246pub type PatSource = InFile<PatPtr>;
246 247
248pub type LabelPtr = AstPtr<ast::Label>;
249pub type LabelSource = InFile<LabelPtr>;
247/// An item body together with the mapping from syntax nodes to HIR expression 250/// An item body together with the mapping from syntax nodes to HIR expression
248/// IDs. This is needed to go from e.g. a position in a file to the HIR 251/// IDs. This is needed to go from e.g. a position in a file to the HIR
249/// expression containing it; but for type inference etc., we want to operate on 252/// expression containing it; but for type inference etc., we want to operate on
@@ -261,6 +264,8 @@ pub struct BodySourceMap {
261 expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, 264 expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>,
262 pat_map: FxHashMap<PatSource, PatId>, 265 pat_map: FxHashMap<PatSource, PatId>,
263 pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, 266 pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
267 label_map: FxHashMap<LabelSource, LabelId>,
268 label_map_back: ArenaMap<LabelId, LabelSource>,
264 field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>, 269 field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>,
265 expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, 270 expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
266 271
@@ -334,6 +339,14 @@ impl Index<PatId> for Body {
334 } 339 }
335} 340}
336 341
342impl Index<LabelId> for Body {
343 type Output = Label;
344
345 fn index(&self, label: LabelId) -> &Label {
346 &self.labels[label]
347 }
348}
349
337impl BodySourceMap { 350impl BodySourceMap {
338 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { 351 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
339 self.expr_map_back[expr].clone() 352 self.expr_map_back[expr].clone()
@@ -363,6 +376,15 @@ impl BodySourceMap {
363 self.pat_map.get(&src).cloned() 376 self.pat_map.get(&src).cloned()
364 } 377 }
365 378
379 pub fn label_syntax(&self, label: LabelId) -> LabelSource {
380 self.label_map_back[label].clone()
381 }
382
383 pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
384 let src = node.map(|it| AstPtr::new(it));
385 self.label_map.get(&src).cloned()
386 }
387
366 pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> { 388 pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> {
367 self.field_map[&(expr, field)].clone() 389 self.field_map[&(expr, field)].clone()
368 } 390 }
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 978c3a324..17c72779b 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -22,13 +22,14 @@ use test_utils::mark;
22 22
23use crate::{ 23use crate::{
24 adt::StructKind, 24 adt::StructKind,
25 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, 25 body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax},
26 builtin_type::{BuiltinFloat, BuiltinInt}, 26 builtin_type::{BuiltinFloat, BuiltinInt},
27 db::DefDatabase, 27 db::DefDatabase,
28 diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro}, 28 diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro},
29 expr::{ 29 expr::{
30 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, 30 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Label,
31 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 31 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField,
32 Statement,
32 }, 33 },
33 item_scope::BuiltinShadowMode, 34 item_scope::BuiltinShadowMode,
34 item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, 35 item_tree::{ItemTree, ItemTreeId, ItemTreeNode},
@@ -72,6 +73,7 @@ pub(super) fn lower(
72 body: Body { 73 body: Body {
73 exprs: Arena::default(), 74 exprs: Arena::default(),
74 pats: Arena::default(), 75 pats: Arena::default(),
76 labels: Arena::default(),
75 params: Vec::new(), 77 params: Vec::new(),
76 body_expr: dummy_expr_id(), 78 body_expr: dummy_expr_id(),
77 item_scope: Default::default(), 79 item_scope: Default::default(),
@@ -175,6 +177,18 @@ impl ExprCollector<'_> {
175 id 177 id
176 } 178 }
177 179
180 fn alloc_label(&mut self, label: Label, ptr: AstPtr<ast::Label>) -> LabelId {
181 let src = self.expander.to_source(ptr);
182 let id = self.make_label(label, src.clone());
183 self.source_map.label_map.insert(src, id);
184 id
185 }
186 fn make_label(&mut self, label: Label, src: LabelSource) -> LabelId {
187 let id = self.body.labels.alloc(label);
188 self.source_map.label_map_back.insert(id, src);
189 id
190 }
191
178 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 192 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
179 let syntax_ptr = AstPtr::new(&expr); 193 let syntax_ptr = AstPtr::new(&expr);
180 if self.check_cfg(&expr).is_none() { 194 if self.check_cfg(&expr).is_none() {
@@ -228,37 +242,40 @@ impl ExprCollector<'_> {
228 self.alloc_expr(Expr::Unsafe { body }, syntax_ptr) 242 self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
229 } 243 }
230 // FIXME: we need to record these effects somewhere... 244 // FIXME: we need to record these effects somewhere...
231 ast::Effect::Label(label) => match e.block_expr() { 245 ast::Effect::Label(label) => {
232 Some(block) => { 246 let label = self.collect_label(label);
233 let res = self.collect_block(block); 247 match e.block_expr() {
234 match &mut self.body.exprs[res] { 248 Some(block) => {
235 Expr::Block { label: block_label, .. } => { 249 let res = self.collect_block(block);
236 *block_label = label.lifetime().map(|t| Name::new_lifetime(&t)) 250 match &mut self.body.exprs[res] {
251 Expr::Block { label: block_label, .. } => {
252 *block_label = Some(label);
253 }
254 _ => unreachable!(),
237 } 255 }
238 _ => unreachable!(), 256 res
239 } 257 }
240 res 258 None => self.missing_expr(),
241 } 259 }
242 None => self.missing_expr(), 260 }
243 },
244 // FIXME: we need to record these effects somewhere... 261 // FIXME: we need to record these effects somewhere...
245 ast::Effect::Async(_) => { 262 ast::Effect::Async(_) => {
246 let body = self.collect_block_opt(e.block_expr()); 263 let body = self.collect_block_opt(e.block_expr());
247 self.alloc_expr(Expr::Async { body }, syntax_ptr) 264 self.alloc_expr(Expr::Async { body }, syntax_ptr)
248 } 265 }
266 ast::Effect::Const(_) => {
267 let body = self.collect_block_opt(e.block_expr());
268 self.alloc_expr(Expr::Const { body }, syntax_ptr)
269 }
249 }, 270 },
250 ast::Expr::BlockExpr(e) => self.collect_block(e), 271 ast::Expr::BlockExpr(e) => self.collect_block(e),
251 ast::Expr::LoopExpr(e) => { 272 ast::Expr::LoopExpr(e) => {
273 let label = e.label().map(|label| self.collect_label(label));
252 let body = self.collect_block_opt(e.loop_body()); 274 let body = self.collect_block_opt(e.loop_body());
253 self.alloc_expr( 275 self.alloc_expr(Expr::Loop { body, label }, syntax_ptr)
254 Expr::Loop {
255 body,
256 label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
257 },
258 syntax_ptr,
259 )
260 } 276 }
261 ast::Expr::WhileExpr(e) => { 277 ast::Expr::WhileExpr(e) => {
278 let label = e.label().map(|label| self.collect_label(label));
262 let body = self.collect_block_opt(e.loop_body()); 279 let body = self.collect_block_opt(e.loop_body());
263 280
264 let condition = match e.condition() { 281 let condition = match e.condition() {
@@ -279,42 +296,20 @@ impl ExprCollector<'_> {
279 ]; 296 ];
280 let match_expr = 297 let match_expr =
281 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); 298 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
282 return self.alloc_expr( 299 return self
283 Expr::Loop { 300 .alloc_expr(Expr::Loop { body: match_expr, label }, syntax_ptr);
284 body: match_expr,
285 label: e
286 .label()
287 .and_then(|l| l.lifetime())
288 .map(|l| Name::new_lifetime(&l)),
289 },
290 syntax_ptr,
291 );
292 } 301 }
293 }, 302 },
294 }; 303 };
295 304
296 self.alloc_expr( 305 self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr)
297 Expr::While {
298 condition,
299 body,
300 label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
301 },
302 syntax_ptr,
303 )
304 } 306 }
305 ast::Expr::ForExpr(e) => { 307 ast::Expr::ForExpr(e) => {
308 let label = e.label().map(|label| self.collect_label(label));
306 let iterable = self.collect_expr_opt(e.iterable()); 309 let iterable = self.collect_expr_opt(e.iterable());
307 let pat = self.collect_pat_opt(e.pat()); 310 let pat = self.collect_pat_opt(e.pat());
308 let body = self.collect_block_opt(e.loop_body()); 311 let body = self.collect_block_opt(e.loop_body());
309 self.alloc_expr( 312 self.alloc_expr(Expr::For { iterable, pat, body, label }, syntax_ptr)
310 Expr::For {
311 iterable,
312 pat,
313 body,
314 label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
315 },
316 syntax_ptr,
317 )
318 } 313 }
319 ast::Expr::CallExpr(e) => { 314 ast::Expr::CallExpr(e) => {
320 let callee = self.collect_expr_opt(e.expr()); 315 let callee = self.collect_expr_opt(e.expr());
@@ -814,6 +809,13 @@ impl ExprCollector<'_> {
814 } 809 }
815 } 810 }
816 811
812 fn collect_label(&mut self, ast_label: ast::Label) -> LabelId {
813 let label = Label {
814 name: ast_label.lifetime().as_ref().map_or_else(Name::missing, Name::new_lifetime),
815 };
816 self.alloc_label(label, AstPtr::new(&ast_label))
817 }
818
817 fn collect_pat(&mut self, pat: ast::Pat) -> PatId { 819 fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
818 let pattern = match &pat { 820 let pattern = match &pat {
819 ast::Pat::IdentPat(bp) => { 821 ast::Pat::IdentPat(bp) => {
@@ -932,10 +934,16 @@ impl ExprCollector<'_> {
932 let inner = self.collect_pat_opt(boxpat.pat()); 934 let inner = self.collect_pat_opt(boxpat.pat());
933 Pat::Box { inner } 935 Pat::Box { inner }
934 } 936 }
935 // FIXME: implement 937 ast::Pat::ConstBlockPat(const_block_pat) => {
936 ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => { 938 if let Some(expr) = const_block_pat.block_expr() {
937 Pat::Missing 939 let expr_id = self.collect_block(expr);
940 Pat::ConstBlock(expr_id)
941 } else {
942 Pat::Missing
943 }
938 } 944 }
945 // FIXME: implement
946 ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
939 }; 947 };
940 let ptr = AstPtr::new(&pat); 948 let ptr = AstPtr::new(&pat);
941 self.alloc_pat(pattern, Either::Left(ptr)) 949 self.alloc_pat(pattern, Either::Left(ptr))
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index e5d740a36..6a481769d 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -30,6 +30,12 @@ pub(crate) fn dummy_expr_id() -> ExprId {
30pub type PatId = Idx<Pat>; 30pub type PatId = Idx<Pat>;
31 31
32#[derive(Debug, Clone, Eq, PartialEq)] 32#[derive(Debug, Clone, Eq, PartialEq)]
33pub struct Label {
34 pub name: Name,
35}
36pub type LabelId = Idx<Label>;
37
38#[derive(Debug, Clone, Eq, PartialEq)]
33pub enum Literal { 39pub enum Literal {
34 String(String), 40 String(String),
35 ByteString(Vec<u8>), 41 ByteString(Vec<u8>),
@@ -52,22 +58,22 @@ pub enum Expr {
52 Block { 58 Block {
53 statements: Vec<Statement>, 59 statements: Vec<Statement>,
54 tail: Option<ExprId>, 60 tail: Option<ExprId>,
55 label: Option<Name>, 61 label: Option<LabelId>,
56 }, 62 },
57 Loop { 63 Loop {
58 body: ExprId, 64 body: ExprId,
59 label: Option<Name>, 65 label: Option<LabelId>,
60 }, 66 },
61 While { 67 While {
62 condition: ExprId, 68 condition: ExprId,
63 body: ExprId, 69 body: ExprId,
64 label: Option<Name>, 70 label: Option<LabelId>,
65 }, 71 },
66 For { 72 For {
67 iterable: ExprId, 73 iterable: ExprId,
68 pat: PatId, 74 pat: PatId,
69 body: ExprId, 75 body: ExprId,
70 label: Option<Name>, 76 label: Option<LabelId>,
71 }, 77 },
72 Call { 78 Call {
73 callee: ExprId, 79 callee: ExprId,
@@ -114,6 +120,9 @@ pub enum Expr {
114 Async { 120 Async {
115 body: ExprId, 121 body: ExprId,
116 }, 122 },
123 Const {
124 body: ExprId,
125 },
117 Cast { 126 Cast {
118 expr: ExprId, 127 expr: ExprId,
119 type_ref: TypeRef, 128 type_ref: TypeRef,
@@ -253,7 +262,10 @@ impl Expr {
253 f(*expr); 262 f(*expr);
254 } 263 }
255 } 264 }
256 Expr::TryBlock { body } | Expr::Unsafe { body } | Expr::Async { body } => f(*body), 265 Expr::TryBlock { body }
266 | Expr::Unsafe { body }
267 | Expr::Async { body }
268 | Expr::Const { body } => f(*body),
257 Expr::Loop { body, .. } => f(*body), 269 Expr::Loop { body, .. } => f(*body),
258 Expr::While { condition, body, .. } => { 270 Expr::While { condition, body, .. } => {
259 f(*condition); 271 f(*condition);
@@ -399,12 +411,18 @@ pub enum Pat {
399 TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, 411 TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> },
400 Ref { pat: PatId, mutability: Mutability }, 412 Ref { pat: PatId, mutability: Mutability },
401 Box { inner: PatId }, 413 Box { inner: PatId },
414 ConstBlock(ExprId),
402} 415}
403 416
404impl Pat { 417impl Pat {
405 pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { 418 pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
406 match self { 419 match self {
407 Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {} 420 Pat::Range { .. }
421 | Pat::Lit(..)
422 | Pat::Path(..)
423 | Pat::ConstBlock(..)
424 | Pat::Wild
425 | Pat::Missing => {}
408 Pat::Bind { subpat, .. } => { 426 Pat::Bind { subpat, .. } => {
409 subpat.iter().copied().for_each(f); 427 subpat.iter().copied().for_each(f);
410 } 428 }
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index f9bf5bc72..e5e9e8ca1 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -677,7 +677,7 @@ fn macro_expansion_overflow() {
677 r#" 677 r#"
678macro_rules! a { 678macro_rules! a {
679 ($e:expr; $($t:tt)*) => { 679 ($e:expr; $($t:tt)*) => {
680 b!($($t)*); 680 b!(static = (); $($t)*);
681 }; 681 };
682 () => {}; 682 () => {};
683} 683}
@@ -689,7 +689,7 @@ macro_rules! b {
689 () => {}; 689 () => {};
690} 690}
691 691
692b! { static = #[] (); } 692b! { static = #[] ();}
693"#, 693"#,
694 expect![[r#" 694 expect![[r#"
695 crate 695 crate