diff options
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 49 | ||||
-rw-r--r-- | crates/ra_hir_def/src/builtin_type.rs | 86 | ||||
-rw-r--r-- | crates/ra_hir_def/src/expr.rs | 419 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 2 |
5 files changed, 542 insertions, 16 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs new file mode 100644 index 000000000..7447904ea --- /dev/null +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -0,0 +1,2 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | mod lower; | ||
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs new file mode 100644 index 000000000..1a144b1f9 --- /dev/null +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -0,0 +1,49 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use ra_syntax::ast; | ||
4 | |||
5 | use crate::expr::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering}; | ||
6 | |||
7 | impl From<ast::BinOp> for BinaryOp { | ||
8 | fn from(ast_op: ast::BinOp) -> Self { | ||
9 | match ast_op { | ||
10 | ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or), | ||
11 | ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And), | ||
12 | ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }), | ||
13 | ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }), | ||
14 | ast::BinOp::LesserEqualTest => { | ||
15 | BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false }) | ||
16 | } | ||
17 | ast::BinOp::GreaterEqualTest => { | ||
18 | BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false }) | ||
19 | } | ||
20 | ast::BinOp::LesserTest => { | ||
21 | BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true }) | ||
22 | } | ||
23 | ast::BinOp::GreaterTest => { | ||
24 | BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true }) | ||
25 | } | ||
26 | ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add), | ||
27 | ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul), | ||
28 | ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub), | ||
29 | ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div), | ||
30 | ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem), | ||
31 | ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl), | ||
32 | ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr), | ||
33 | ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor), | ||
34 | ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr), | ||
35 | ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd), | ||
36 | ast::BinOp::Assignment => BinaryOp::Assignment { op: None }, | ||
37 | ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) }, | ||
38 | ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) }, | ||
39 | ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) }, | ||
40 | ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) }, | ||
41 | ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) }, | ||
42 | ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) }, | ||
43 | ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) }, | ||
44 | ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) }, | ||
45 | ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) }, | ||
46 | ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) }, | ||
47 | } | ||
48 | } | ||
49 | } | ||
diff --git a/crates/ra_hir_def/src/builtin_type.rs b/crates/ra_hir_def/src/builtin_type.rs index 996e86fd9..5e8157144 100644 --- a/crates/ra_hir_def/src/builtin_type.rs +++ b/crates/ra_hir_def/src/builtin_type.rs | |||
@@ -56,22 +56,22 @@ impl BuiltinType { | |||
56 | (name::BOOL, BuiltinType::Bool), | 56 | (name::BOOL, BuiltinType::Bool), |
57 | (name::STR, BuiltinType::Str ), | 57 | (name::STR, BuiltinType::Str ), |
58 | 58 | ||
59 | (name::ISIZE, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize })), | 59 | (name::ISIZE, BuiltinType::Int(BuiltinInt::ISIZE)), |
60 | (name::I8, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 })), | 60 | (name::I8, BuiltinType::Int(BuiltinInt::I8)), |
61 | (name::I16, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 })), | 61 | (name::I16, BuiltinType::Int(BuiltinInt::I16)), |
62 | (name::I32, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 })), | 62 | (name::I32, BuiltinType::Int(BuiltinInt::I32)), |
63 | (name::I64, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 })), | 63 | (name::I64, BuiltinType::Int(BuiltinInt::I64)), |
64 | (name::I128, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 })), | 64 | (name::I128, BuiltinType::Int(BuiltinInt::I128)), |
65 | 65 | ||
66 | (name::USIZE, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize })), | 66 | (name::USIZE, BuiltinType::Int(BuiltinInt::USIZE)), |
67 | (name::U8, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 })), | 67 | (name::U8, BuiltinType::Int(BuiltinInt::U8)), |
68 | (name::U16, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 })), | 68 | (name::U16, BuiltinType::Int(BuiltinInt::U16)), |
69 | (name::U32, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 })), | 69 | (name::U32, BuiltinType::Int(BuiltinInt::U32)), |
70 | (name::U64, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 })), | 70 | (name::U64, BuiltinType::Int(BuiltinInt::U64)), |
71 | (name::U128, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 })), | 71 | (name::U128, BuiltinType::Int(BuiltinInt::U128)), |
72 | 72 | ||
73 | (name::F32, BuiltinType::Float(BuiltinFloat { bitness: FloatBitness::X32 })), | 73 | (name::F32, BuiltinType::Float(BuiltinFloat::F32)), |
74 | (name::F64, BuiltinType::Float(BuiltinFloat { bitness: FloatBitness::X64 })), | 74 | (name::F64, BuiltinType::Float(BuiltinFloat::F64)), |
75 | ]; | 75 | ]; |
76 | } | 76 | } |
77 | 77 | ||
@@ -104,3 +104,57 @@ impl fmt::Display for BuiltinType { | |||
104 | f.write_str(type_name) | 104 | f.write_str(type_name) |
105 | } | 105 | } |
106 | } | 106 | } |
107 | |||
108 | #[rustfmt::skip] | ||
109 | impl BuiltinInt { | ||
110 | pub const ISIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize }; | ||
111 | pub const I8 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 }; | ||
112 | pub const I16 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 }; | ||
113 | pub const I32 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 }; | ||
114 | pub const I64 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 }; | ||
115 | pub const I128 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 }; | ||
116 | |||
117 | pub const USIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize }; | ||
118 | pub const U8 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 }; | ||
119 | pub const U16 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 }; | ||
120 | pub const U32 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 }; | ||
121 | pub const U64 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 }; | ||
122 | pub const U128 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 }; | ||
123 | |||
124 | |||
125 | pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> { | ||
126 | let res = match suffix { | ||
127 | "isize" => Self::ISIZE, | ||
128 | "i8" => Self::I8, | ||
129 | "i16" => Self::I16, | ||
130 | "i32" => Self::I32, | ||
131 | "i64" => Self::I64, | ||
132 | "i128" => Self::I128, | ||
133 | |||
134 | "usize" => Self::USIZE, | ||
135 | "u8" => Self::U8, | ||
136 | "u16" => Self::U16, | ||
137 | "u32" => Self::U32, | ||
138 | "u64" => Self::U64, | ||
139 | "u128" => Self::U128, | ||
140 | |||
141 | _ => return None, | ||
142 | }; | ||
143 | Some(res) | ||
144 | } | ||
145 | } | ||
146 | |||
147 | #[rustfmt::skip] | ||
148 | impl BuiltinFloat { | ||
149 | pub const F32: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X32 }; | ||
150 | pub const F64: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X64 }; | ||
151 | |||
152 | pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> { | ||
153 | let res = match suffix { | ||
154 | "f32" => BuiltinFloat::F32, | ||
155 | "f64" => BuiltinFloat::F64, | ||
156 | _ => return None, | ||
157 | }; | ||
158 | Some(res) | ||
159 | } | ||
160 | } | ||
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs new file mode 100644 index 000000000..12eb0da68 --- /dev/null +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -0,0 +1,419 @@ | |||
1 | //! This module describes hir-level representation of expressions. | ||
2 | //! | ||
3 | //! This representaion is: | ||
4 | //! | ||
5 | //! 1. Identity-based. Each expression has an `id`, so we can distinguish | ||
6 | //! between different `1` in `1 + 1`. | ||
7 | //! 2. Independent of syntax. Though syntactic provenance information can be | ||
8 | //! attached separately via id-based side map. | ||
9 | //! 3. Unresolved. Paths are stored as sequences of names, and not as defs the | ||
10 | //! names refer to. | ||
11 | //! 4. Desugared. There's no `if let`. | ||
12 | |||
13 | use hir_expand::name::Name; | ||
14 | use ra_arena::{impl_arena_id, RawId}; | ||
15 | |||
16 | use crate::{ | ||
17 | builtin_type::{BuiltinFloat, BuiltinInt}, | ||
18 | path::{GenericArgs, Path}, | ||
19 | type_ref::{Mutability, TypeRef}, | ||
20 | }; | ||
21 | |||
22 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
23 | pub struct ExprId(RawId); | ||
24 | impl_arena_id!(ExprId); | ||
25 | |||
26 | impl ExprId { | ||
27 | pub fn dummy() -> ExprId { | ||
28 | ExprId((!0).into()) | ||
29 | } | ||
30 | } | ||
31 | |||
32 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
33 | pub struct PatId(RawId); | ||
34 | impl_arena_id!(PatId); | ||
35 | |||
36 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
37 | pub enum Literal { | ||
38 | String(String), | ||
39 | ByteString(Vec<u8>), | ||
40 | Char(char), | ||
41 | Bool(bool), | ||
42 | Int(u64, Option<BuiltinInt>), | ||
43 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq | ||
44 | } | ||
45 | |||
46 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
47 | pub enum Expr { | ||
48 | /// This is produced if syntax tree does not have a required expression piece. | ||
49 | Missing, | ||
50 | Path(Path), | ||
51 | If { | ||
52 | condition: ExprId, | ||
53 | then_branch: ExprId, | ||
54 | else_branch: Option<ExprId>, | ||
55 | }, | ||
56 | Block { | ||
57 | statements: Vec<Statement>, | ||
58 | tail: Option<ExprId>, | ||
59 | }, | ||
60 | Loop { | ||
61 | body: ExprId, | ||
62 | }, | ||
63 | While { | ||
64 | condition: ExprId, | ||
65 | body: ExprId, | ||
66 | }, | ||
67 | For { | ||
68 | iterable: ExprId, | ||
69 | pat: PatId, | ||
70 | body: ExprId, | ||
71 | }, | ||
72 | Call { | ||
73 | callee: ExprId, | ||
74 | args: Vec<ExprId>, | ||
75 | }, | ||
76 | MethodCall { | ||
77 | receiver: ExprId, | ||
78 | method_name: Name, | ||
79 | args: Vec<ExprId>, | ||
80 | generic_args: Option<GenericArgs>, | ||
81 | }, | ||
82 | Match { | ||
83 | expr: ExprId, | ||
84 | arms: Vec<MatchArm>, | ||
85 | }, | ||
86 | Continue, | ||
87 | Break { | ||
88 | expr: Option<ExprId>, | ||
89 | }, | ||
90 | Return { | ||
91 | expr: Option<ExprId>, | ||
92 | }, | ||
93 | RecordLit { | ||
94 | path: Option<Path>, | ||
95 | fields: Vec<RecordLitField>, | ||
96 | spread: Option<ExprId>, | ||
97 | }, | ||
98 | Field { | ||
99 | expr: ExprId, | ||
100 | name: Name, | ||
101 | }, | ||
102 | Await { | ||
103 | expr: ExprId, | ||
104 | }, | ||
105 | Try { | ||
106 | expr: ExprId, | ||
107 | }, | ||
108 | TryBlock { | ||
109 | body: ExprId, | ||
110 | }, | ||
111 | Cast { | ||
112 | expr: ExprId, | ||
113 | type_ref: TypeRef, | ||
114 | }, | ||
115 | Ref { | ||
116 | expr: ExprId, | ||
117 | mutability: Mutability, | ||
118 | }, | ||
119 | Box { | ||
120 | expr: ExprId, | ||
121 | }, | ||
122 | UnaryOp { | ||
123 | expr: ExprId, | ||
124 | op: UnaryOp, | ||
125 | }, | ||
126 | BinaryOp { | ||
127 | lhs: ExprId, | ||
128 | rhs: ExprId, | ||
129 | op: Option<BinaryOp>, | ||
130 | }, | ||
131 | Index { | ||
132 | base: ExprId, | ||
133 | index: ExprId, | ||
134 | }, | ||
135 | Lambda { | ||
136 | args: Vec<PatId>, | ||
137 | arg_types: Vec<Option<TypeRef>>, | ||
138 | body: ExprId, | ||
139 | }, | ||
140 | Tuple { | ||
141 | exprs: Vec<ExprId>, | ||
142 | }, | ||
143 | Array(Array), | ||
144 | Literal(Literal), | ||
145 | } | ||
146 | |||
147 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | ||
148 | pub enum BinaryOp { | ||
149 | LogicOp(LogicOp), | ||
150 | ArithOp(ArithOp), | ||
151 | CmpOp(CmpOp), | ||
152 | Assignment { op: Option<ArithOp> }, | ||
153 | } | ||
154 | |||
155 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | ||
156 | pub enum LogicOp { | ||
157 | And, | ||
158 | Or, | ||
159 | } | ||
160 | |||
161 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | ||
162 | pub enum CmpOp { | ||
163 | Eq { negated: bool }, | ||
164 | Ord { ordering: Ordering, strict: bool }, | ||
165 | } | ||
166 | |||
167 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | ||
168 | pub enum Ordering { | ||
169 | Less, | ||
170 | Greater, | ||
171 | } | ||
172 | |||
173 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | ||
174 | pub enum ArithOp { | ||
175 | Add, | ||
176 | Mul, | ||
177 | Sub, | ||
178 | Div, | ||
179 | Rem, | ||
180 | Shl, | ||
181 | Shr, | ||
182 | BitXor, | ||
183 | BitOr, | ||
184 | BitAnd, | ||
185 | } | ||
186 | |||
187 | pub use ra_syntax::ast::PrefixOp as UnaryOp; | ||
188 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
189 | pub enum Array { | ||
190 | ElementList(Vec<ExprId>), | ||
191 | Repeat { initializer: ExprId, repeat: ExprId }, | ||
192 | } | ||
193 | |||
194 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
195 | pub struct MatchArm { | ||
196 | pub pats: Vec<PatId>, | ||
197 | pub guard: Option<ExprId>, | ||
198 | pub expr: ExprId, | ||
199 | } | ||
200 | |||
201 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
202 | pub struct RecordLitField { | ||
203 | pub name: Name, | ||
204 | pub expr: ExprId, | ||
205 | } | ||
206 | |||
207 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
208 | pub enum Statement { | ||
209 | Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> }, | ||
210 | Expr(ExprId), | ||
211 | } | ||
212 | |||
213 | impl Expr { | ||
214 | pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) { | ||
215 | match self { | ||
216 | Expr::Missing => {} | ||
217 | Expr::Path(_) => {} | ||
218 | Expr::If { condition, then_branch, else_branch } => { | ||
219 | f(*condition); | ||
220 | f(*then_branch); | ||
221 | if let Some(else_branch) = else_branch { | ||
222 | f(*else_branch); | ||
223 | } | ||
224 | } | ||
225 | Expr::Block { statements, tail } => { | ||
226 | for stmt in statements { | ||
227 | match stmt { | ||
228 | Statement::Let { initializer, .. } => { | ||
229 | if let Some(expr) = initializer { | ||
230 | f(*expr); | ||
231 | } | ||
232 | } | ||
233 | Statement::Expr(e) => f(*e), | ||
234 | } | ||
235 | } | ||
236 | if let Some(expr) = tail { | ||
237 | f(*expr); | ||
238 | } | ||
239 | } | ||
240 | Expr::TryBlock { body } => f(*body), | ||
241 | Expr::Loop { body } => f(*body), | ||
242 | Expr::While { condition, body } => { | ||
243 | f(*condition); | ||
244 | f(*body); | ||
245 | } | ||
246 | Expr::For { iterable, body, .. } => { | ||
247 | f(*iterable); | ||
248 | f(*body); | ||
249 | } | ||
250 | Expr::Call { callee, args } => { | ||
251 | f(*callee); | ||
252 | for arg in args { | ||
253 | f(*arg); | ||
254 | } | ||
255 | } | ||
256 | Expr::MethodCall { receiver, args, .. } => { | ||
257 | f(*receiver); | ||
258 | for arg in args { | ||
259 | f(*arg); | ||
260 | } | ||
261 | } | ||
262 | Expr::Match { expr, arms } => { | ||
263 | f(*expr); | ||
264 | for arm in arms { | ||
265 | f(arm.expr); | ||
266 | } | ||
267 | } | ||
268 | Expr::Continue => {} | ||
269 | Expr::Break { expr } | Expr::Return { expr } => { | ||
270 | if let Some(expr) = expr { | ||
271 | f(*expr); | ||
272 | } | ||
273 | } | ||
274 | Expr::RecordLit { fields, spread, .. } => { | ||
275 | for field in fields { | ||
276 | f(field.expr); | ||
277 | } | ||
278 | if let Some(expr) = spread { | ||
279 | f(*expr); | ||
280 | } | ||
281 | } | ||
282 | Expr::Lambda { body, .. } => { | ||
283 | f(*body); | ||
284 | } | ||
285 | Expr::BinaryOp { lhs, rhs, .. } => { | ||
286 | f(*lhs); | ||
287 | f(*rhs); | ||
288 | } | ||
289 | Expr::Index { base, index } => { | ||
290 | f(*base); | ||
291 | f(*index); | ||
292 | } | ||
293 | Expr::Field { expr, .. } | ||
294 | | Expr::Await { expr } | ||
295 | | Expr::Try { expr } | ||
296 | | Expr::Cast { expr, .. } | ||
297 | | Expr::Ref { expr, .. } | ||
298 | | Expr::UnaryOp { expr, .. } | ||
299 | | Expr::Box { expr } => { | ||
300 | f(*expr); | ||
301 | } | ||
302 | Expr::Tuple { exprs } => { | ||
303 | for expr in exprs { | ||
304 | f(*expr); | ||
305 | } | ||
306 | } | ||
307 | Expr::Array(a) => match a { | ||
308 | Array::ElementList(exprs) => { | ||
309 | for expr in exprs { | ||
310 | f(*expr); | ||
311 | } | ||
312 | } | ||
313 | Array::Repeat { initializer, repeat } => { | ||
314 | f(*initializer); | ||
315 | f(*repeat) | ||
316 | } | ||
317 | }, | ||
318 | Expr::Literal(_) => {} | ||
319 | } | ||
320 | } | ||
321 | } | ||
322 | |||
323 | /// Explicit binding annotations given in the HIR for a binding. Note | ||
324 | /// that this is not the final binding *mode* that we infer after type | ||
325 | /// inference. | ||
326 | #[derive(Clone, PartialEq, Eq, Debug, Copy)] | ||
327 | pub enum BindingAnnotation { | ||
328 | /// No binding annotation given: this means that the final binding mode | ||
329 | /// will depend on whether we have skipped through a `&` reference | ||
330 | /// when matching. For example, the `x` in `Some(x)` will have binding | ||
331 | /// mode `None`; if you do `let Some(x) = &Some(22)`, it will | ||
332 | /// ultimately be inferred to be by-reference. | ||
333 | Unannotated, | ||
334 | |||
335 | /// Annotated with `mut x` -- could be either ref or not, similar to `None`. | ||
336 | Mutable, | ||
337 | |||
338 | /// Annotated as `ref`, like `ref x` | ||
339 | Ref, | ||
340 | |||
341 | /// Annotated as `ref mut x`. | ||
342 | RefMut, | ||
343 | } | ||
344 | |||
345 | impl BindingAnnotation { | ||
346 | pub fn new(is_mutable: bool, is_ref: bool) -> Self { | ||
347 | match (is_mutable, is_ref) { | ||
348 | (true, true) => BindingAnnotation::RefMut, | ||
349 | (false, true) => BindingAnnotation::Ref, | ||
350 | (true, false) => BindingAnnotation::Mutable, | ||
351 | (false, false) => BindingAnnotation::Unannotated, | ||
352 | } | ||
353 | } | ||
354 | } | ||
355 | |||
356 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
357 | pub struct RecordFieldPat { | ||
358 | pub name: Name, | ||
359 | pub pat: PatId, | ||
360 | } | ||
361 | |||
362 | /// Close relative to rustc's hir::PatKind | ||
363 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
364 | pub enum Pat { | ||
365 | Missing, | ||
366 | Wild, | ||
367 | Tuple(Vec<PatId>), | ||
368 | Record { | ||
369 | path: Option<Path>, | ||
370 | args: Vec<RecordFieldPat>, | ||
371 | // FIXME: 'ellipsis' option | ||
372 | }, | ||
373 | Range { | ||
374 | start: ExprId, | ||
375 | end: ExprId, | ||
376 | }, | ||
377 | Slice { | ||
378 | prefix: Vec<PatId>, | ||
379 | rest: Option<PatId>, | ||
380 | suffix: Vec<PatId>, | ||
381 | }, | ||
382 | Path(Path), | ||
383 | Lit(ExprId), | ||
384 | Bind { | ||
385 | mode: BindingAnnotation, | ||
386 | name: Name, | ||
387 | subpat: Option<PatId>, | ||
388 | }, | ||
389 | TupleStruct { | ||
390 | path: Option<Path>, | ||
391 | args: Vec<PatId>, | ||
392 | }, | ||
393 | Ref { | ||
394 | pat: PatId, | ||
395 | mutability: Mutability, | ||
396 | }, | ||
397 | } | ||
398 | |||
399 | impl Pat { | ||
400 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { | ||
401 | match self { | ||
402 | Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {} | ||
403 | Pat::Bind { subpat, .. } => { | ||
404 | subpat.iter().copied().for_each(f); | ||
405 | } | ||
406 | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { | ||
407 | args.iter().copied().for_each(f); | ||
408 | } | ||
409 | Pat::Ref { pat, .. } => f(*pat), | ||
410 | Pat::Slice { prefix, rest, suffix } => { | ||
411 | let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter()); | ||
412 | total_iter.copied().for_each(f); | ||
413 | } | ||
414 | Pat::Record { args, .. } => { | ||
415 | args.iter().map(|f| f.pat).for_each(f); | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | } | ||
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 239317efe..4a758bb83 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -14,6 +14,8 @@ pub mod type_ref; | |||
14 | pub mod builtin_type; | 14 | pub mod builtin_type; |
15 | pub mod adt; | 15 | pub mod adt; |
16 | pub mod diagnostics; | 16 | pub mod diagnostics; |
17 | pub mod expr; | ||
18 | pub mod body; | ||
17 | 19 | ||
18 | #[cfg(test)] | 20 | #[cfg(test)] |
19 | mod test_db; | 21 | mod test_db; |