]> git.lizzy.rs Git - rust.git/blob - crates/ra_hir_def/src/body/lower.rs
0d3f946df639279d8cf5adbee1e0dbb4bbcd8257
[rust.git] / crates / ra_hir_def / src / body / lower.rs
1 //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2 //! representation.
3
4 use either::Either;
5
6 use hir_expand::name::{name, AsName, Name};
7 use ra_arena::Arena;
8 use ra_syntax::{
9     ast::{
10         self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
11         TypeAscriptionOwner,
12     },
13     AstNode, AstPtr,
14 };
15 use test_utils::tested_by;
16
17 use crate::{
18     body::{Body, BodySourceMap, Expander, PatPtr},
19     builtin_type::{BuiltinFloat, BuiltinInt},
20     db::DefDatabase,
21     expr::{
22         ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
23         MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
24     },
25     path::GenericArgs,
26     path::Path,
27     type_ref::{Mutability, TypeRef},
28     ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StructLoc, UnionLoc,
29 };
30
31 pub(super) fn lower(
32     db: &impl DefDatabase,
33     def: DefWithBodyId,
34     expander: Expander,
35     params: Option<ast::ParamList>,
36     body: Option<ast::Expr>,
37 ) -> (Body, BodySourceMap) {
38     ExprCollector {
39         db,
40         def,
41         expander,
42         source_map: BodySourceMap::default(),
43         body: Body {
44             exprs: Arena::default(),
45             pats: Arena::default(),
46             params: Vec::new(),
47             body_expr: ExprId::dummy(),
48             defs: Vec::new(),
49         },
50     }
51     .collect(params, body)
52 }
53
54 struct ExprCollector<DB> {
55     db: DB,
56     def: DefWithBodyId,
57     expander: Expander,
58
59     body: Body,
60     source_map: BodySourceMap,
61 }
62
63 impl<'a, DB> ExprCollector<&'a DB>
64 where
65     DB: DefDatabase,
66 {
67     fn collect(
68         mut self,
69         param_list: Option<ast::ParamList>,
70         body: Option<ast::Expr>,
71     ) -> (Body, BodySourceMap) {
72         if let Some(param_list) = param_list {
73             if let Some(self_param) = param_list.self_param() {
74                 let ptr = AstPtr::new(&self_param);
75                 let param_pat = self.alloc_pat(
76                     Pat::Bind {
77                         name: name![self],
78                         mode: BindingAnnotation::Unannotated,
79                         subpat: None,
80                     },
81                     Either::Right(ptr),
82                 );
83                 self.body.params.push(param_pat);
84             }
85
86             for param in param_list.params() {
87                 let pat = match param.pat() {
88                     None => continue,
89                     Some(pat) => pat,
90                 };
91                 let param_pat = self.collect_pat(pat);
92                 self.body.params.push(param_pat);
93             }
94         };
95
96         self.body.body_expr = self.collect_expr_opt(body);
97         (self.body, self.source_map)
98     }
99
100     fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
101         let ptr = Either::Left(ptr);
102         let id = self.body.exprs.alloc(expr);
103         let src = self.expander.to_source(ptr);
104         self.source_map.expr_map.insert(src, id);
105         self.source_map.expr_map_back.insert(id, src);
106         id
107     }
108     // desugared exprs don't have ptr, that's wrong and should be fixed
109     // somehow.
110     fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
111         self.body.exprs.alloc(expr)
112     }
113     fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId {
114         let ptr = Either::Right(ptr);
115         let id = self.body.exprs.alloc(expr);
116         let src = self.expander.to_source(ptr);
117         self.source_map.expr_map.insert(src, id);
118         self.source_map.expr_map_back.insert(id, src);
119         id
120     }
121     fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
122         let id = self.body.pats.alloc(pat);
123         let src = self.expander.to_source(ptr);
124         self.source_map.pat_map.insert(src, id);
125         self.source_map.pat_map_back.insert(id, src);
126         id
127     }
128
129     fn empty_block(&mut self) -> ExprId {
130         let block = Expr::Block { statements: Vec::new(), tail: None };
131         self.body.exprs.alloc(block)
132     }
133
134     fn missing_expr(&mut self) -> ExprId {
135         self.body.exprs.alloc(Expr::Missing)
136     }
137
138     fn missing_pat(&mut self) -> PatId {
139         self.body.pats.alloc(Pat::Missing)
140     }
141
142     fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
143         let syntax_ptr = AstPtr::new(&expr);
144         match expr {
145             ast::Expr::IfExpr(e) => {
146                 let then_branch = self.collect_block_opt(e.then_branch());
147
148                 let else_branch = e.else_branch().map(|b| match b {
149                     ast::ElseBranch::Block(it) => self.collect_block(it),
150                     ast::ElseBranch::IfExpr(elif) => {
151                         let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
152                         self.collect_expr(expr)
153                     }
154                 });
155
156                 let condition = match e.condition() {
157                     None => self.missing_expr(),
158                     Some(condition) => match condition.pat() {
159                         None => self.collect_expr_opt(condition.expr()),
160                         // if let -- desugar to match
161                         Some(pat) => {
162                             let pat = self.collect_pat(pat);
163                             let match_expr = self.collect_expr_opt(condition.expr());
164                             let placeholder_pat = self.missing_pat();
165                             let arms = vec![
166                                 MatchArm { pats: vec![pat], expr: then_branch, guard: None },
167                                 MatchArm {
168                                     pats: vec![placeholder_pat],
169                                     expr: else_branch.unwrap_or_else(|| self.empty_block()),
170                                     guard: None,
171                                 },
172                             ];
173                             return self
174                                 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
175                         }
176                     },
177                 };
178
179                 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
180             }
181             ast::Expr::TryBlockExpr(e) => {
182                 let body = self.collect_block_opt(e.body());
183                 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
184             }
185             ast::Expr::BlockExpr(e) => self.collect_block(e),
186             ast::Expr::LoopExpr(e) => {
187                 let body = self.collect_block_opt(e.loop_body());
188                 self.alloc_expr(Expr::Loop { body }, syntax_ptr)
189             }
190             ast::Expr::WhileExpr(e) => {
191                 let body = self.collect_block_opt(e.loop_body());
192
193                 let condition = match e.condition() {
194                     None => self.missing_expr(),
195                     Some(condition) => match condition.pat() {
196                         None => self.collect_expr_opt(condition.expr()),
197                         // if let -- desugar to match
198                         Some(pat) => {
199                             tested_by!(infer_resolve_while_let);
200                             let pat = self.collect_pat(pat);
201                             let match_expr = self.collect_expr_opt(condition.expr());
202                             let placeholder_pat = self.missing_pat();
203                             let break_ = self.alloc_expr_desugared(Expr::Break { expr: None });
204                             let arms = vec![
205                                 MatchArm { pats: vec![pat], expr: body, guard: None },
206                                 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
207                             ];
208                             let match_expr =
209                                 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
210                             return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
211                         }
212                     },
213                 };
214
215                 self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
216             }
217             ast::Expr::ForExpr(e) => {
218                 let iterable = self.collect_expr_opt(e.iterable());
219                 let pat = self.collect_pat_opt(e.pat());
220                 let body = self.collect_block_opt(e.loop_body());
221                 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr)
222             }
223             ast::Expr::CallExpr(e) => {
224                 let callee = self.collect_expr_opt(e.expr());
225                 let args = if let Some(arg_list) = e.arg_list() {
226                     arg_list.args().map(|e| self.collect_expr(e)).collect()
227                 } else {
228                     Vec::new()
229                 };
230                 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
231             }
232             ast::Expr::MethodCallExpr(e) => {
233                 let receiver = self.collect_expr_opt(e.expr());
234                 let args = if let Some(arg_list) = e.arg_list() {
235                     arg_list.args().map(|e| self.collect_expr(e)).collect()
236                 } else {
237                     Vec::new()
238                 };
239                 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
240                 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
241                 self.alloc_expr(
242                     Expr::MethodCall { receiver, method_name, args, generic_args },
243                     syntax_ptr,
244                 )
245             }
246             ast::Expr::MatchExpr(e) => {
247                 let expr = self.collect_expr_opt(e.expr());
248                 let arms = if let Some(match_arm_list) = e.match_arm_list() {
249                     match_arm_list
250                         .arms()
251                         .map(|arm| MatchArm {
252                             pats: arm.pats().map(|p| self.collect_pat(p)).collect(),
253                             expr: self.collect_expr_opt(arm.expr()),
254                             guard: arm
255                                 .guard()
256                                 .and_then(|guard| guard.expr())
257                                 .map(|e| self.collect_expr(e)),
258                         })
259                         .collect()
260                 } else {
261                     Vec::new()
262                 };
263                 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
264             }
265             ast::Expr::PathExpr(e) => {
266                 let path = e
267                     .path()
268                     .and_then(|path| self.expander.parse_path(path))
269                     .map(Expr::Path)
270                     .unwrap_or(Expr::Missing);
271                 self.alloc_expr(path, syntax_ptr)
272             }
273             ast::Expr::ContinueExpr(_e) => {
274                 // FIXME: labels
275                 self.alloc_expr(Expr::Continue, syntax_ptr)
276             }
277             ast::Expr::BreakExpr(e) => {
278                 let expr = e.expr().map(|e| self.collect_expr(e));
279                 self.alloc_expr(Expr::Break { expr }, syntax_ptr)
280             }
281             ast::Expr::ParenExpr(e) => {
282                 let inner = self.collect_expr_opt(e.expr());
283                 // make the paren expr point to the inner expression as well
284                 let src = self.expander.to_source(Either::Left(syntax_ptr));
285                 self.source_map.expr_map.insert(src, inner);
286                 inner
287             }
288             ast::Expr::ReturnExpr(e) => {
289                 let expr = e.expr().map(|e| self.collect_expr(e));
290                 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
291             }
292             ast::Expr::RecordLit(e) => {
293                 let path = e.path().and_then(|path| self.expander.parse_path(path));
294                 let mut field_ptrs = Vec::new();
295                 let record_lit = if let Some(nfl) = e.record_field_list() {
296                     let fields = nfl
297                         .fields()
298                         .inspect(|field| field_ptrs.push(AstPtr::new(field)))
299                         .map(|field| RecordLitField {
300                             name: field
301                                 .name_ref()
302                                 .map(|nr| nr.as_name())
303                                 .unwrap_or_else(Name::missing),
304                             expr: if let Some(e) = field.expr() {
305                                 self.collect_expr(e)
306                             } else if let Some(nr) = field.name_ref() {
307                                 // field shorthand
308                                 self.alloc_expr_field_shorthand(
309                                     Expr::Path(Path::from_name_ref(&nr)),
310                                     AstPtr::new(&field),
311                                 )
312                             } else {
313                                 self.missing_expr()
314                             },
315                         })
316                         .collect();
317                     let spread = nfl.spread().map(|s| self.collect_expr(s));
318                     Expr::RecordLit { path, fields, spread }
319                 } else {
320                     Expr::RecordLit { path, fields: Vec::new(), spread: None }
321                 };
322
323                 let res = self.alloc_expr(record_lit, syntax_ptr);
324                 for (i, ptr) in field_ptrs.into_iter().enumerate() {
325                     self.source_map.field_map.insert((res, i), ptr);
326                 }
327                 res
328             }
329             ast::Expr::FieldExpr(e) => {
330                 let expr = self.collect_expr_opt(e.expr());
331                 let name = match e.field_access() {
332                     Some(kind) => kind.as_name(),
333                     _ => Name::missing(),
334                 };
335                 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
336             }
337             ast::Expr::AwaitExpr(e) => {
338                 let expr = self.collect_expr_opt(e.expr());
339                 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
340             }
341             ast::Expr::TryExpr(e) => {
342                 let expr = self.collect_expr_opt(e.expr());
343                 self.alloc_expr(Expr::Try { expr }, syntax_ptr)
344             }
345             ast::Expr::CastExpr(e) => {
346                 let expr = self.collect_expr_opt(e.expr());
347                 let type_ref = TypeRef::from_ast_opt(e.type_ref());
348                 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
349             }
350             ast::Expr::RefExpr(e) => {
351                 let expr = self.collect_expr_opt(e.expr());
352                 let mutability = Mutability::from_mutable(e.is_mut());
353                 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr)
354             }
355             ast::Expr::PrefixExpr(e) => {
356                 let expr = self.collect_expr_opt(e.expr());
357                 if let Some(op) = e.op_kind() {
358                     self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
359                 } else {
360                     self.alloc_expr(Expr::Missing, syntax_ptr)
361                 }
362             }
363             ast::Expr::LambdaExpr(e) => {
364                 let mut args = Vec::new();
365                 let mut arg_types = Vec::new();
366                 if let Some(pl) = e.param_list() {
367                     for param in pl.params() {
368                         let pat = self.collect_pat_opt(param.pat());
369                         let type_ref = param.ascribed_type().map(TypeRef::from_ast);
370                         args.push(pat);
371                         arg_types.push(type_ref);
372                     }
373                 }
374                 let body = self.collect_expr_opt(e.body());
375                 self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr)
376             }
377             ast::Expr::BinExpr(e) => {
378                 let lhs = self.collect_expr_opt(e.lhs());
379                 let rhs = self.collect_expr_opt(e.rhs());
380                 let op = e.op_kind().map(BinaryOp::from);
381                 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
382             }
383             ast::Expr::TupleExpr(e) => {
384                 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
385                 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
386             }
387             ast::Expr::BoxExpr(e) => {
388                 let expr = self.collect_expr_opt(e.expr());
389                 self.alloc_expr(Expr::Box { expr }, syntax_ptr)
390             }
391
392             ast::Expr::ArrayExpr(e) => {
393                 let kind = e.kind();
394
395                 match kind {
396                     ArrayExprKind::ElementList(e) => {
397                         let exprs = e.map(|expr| self.collect_expr(expr)).collect();
398                         self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
399                     }
400                     ArrayExprKind::Repeat { initializer, repeat } => {
401                         let initializer = self.collect_expr_opt(initializer);
402                         let repeat = self.collect_expr_opt(repeat);
403                         self.alloc_expr(
404                             Expr::Array(Array::Repeat { initializer, repeat }),
405                             syntax_ptr,
406                         )
407                     }
408                 }
409             }
410
411             ast::Expr::Literal(e) => {
412                 let lit = match e.kind() {
413                     LiteralKind::IntNumber { suffix } => {
414                         let known_name = suffix.and_then(|it| BuiltinInt::from_suffix(&it));
415
416                         Literal::Int(Default::default(), known_name)
417                     }
418                     LiteralKind::FloatNumber { suffix } => {
419                         let known_name = suffix.and_then(|it| BuiltinFloat::from_suffix(&it));
420
421                         Literal::Float(Default::default(), known_name)
422                     }
423                     LiteralKind::ByteString => Literal::ByteString(Default::default()),
424                     LiteralKind::String => Literal::String(Default::default()),
425                     LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)),
426                     LiteralKind::Bool => Literal::Bool(Default::default()),
427                     LiteralKind::Char => Literal::Char(Default::default()),
428                 };
429                 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
430             }
431             ast::Expr::IndexExpr(e) => {
432                 let base = self.collect_expr_opt(e.base());
433                 let index = self.collect_expr_opt(e.index());
434                 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
435             }
436             ast::Expr::RangeExpr(e) => {
437                 let lhs = e.start().map(|lhs| self.collect_expr(lhs));
438                 let rhs = e.end().map(|rhs| self.collect_expr(rhs));
439                 match e.op_kind() {
440                     Some(range_type) => {
441                         self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr)
442                     }
443                     None => self.alloc_expr(Expr::Missing, syntax_ptr),
444                 }
445             }
446             // FIXME expand to statements in statement position
447             ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) {
448                 Some((mark, expansion)) => {
449                     let id = self.collect_expr(expansion);
450                     self.expander.exit(self.db, mark);
451                     id
452                 }
453                 None => self.alloc_expr(Expr::Missing, syntax_ptr),
454             },
455
456             // FIXME implement HIR for these:
457             ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
458         }
459     }
460
461     fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
462         if let Some(expr) = expr {
463             self.collect_expr(expr)
464         } else {
465             self.missing_expr()
466         }
467     }
468
469     fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId {
470         let syntax_node_ptr = AstPtr::new(&expr.clone().into());
471         let block = match expr.block() {
472             Some(block) => block,
473             None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
474         };
475         self.collect_block_items(&block);
476         let statements = block
477             .statements()
478             .map(|s| match s {
479                 ast::Stmt::LetStmt(stmt) => {
480                     let pat = self.collect_pat_opt(stmt.pat());
481                     let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
482                     let initializer = stmt.initializer().map(|e| self.collect_expr(e));
483                     Statement::Let { pat, type_ref, initializer }
484                 }
485                 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
486             })
487             .collect();
488         let tail = block.expr().map(|e| self.collect_expr(e));
489         self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
490     }
491
492     fn collect_block_items(&mut self, block: &ast::Block) {
493         let container = ContainerId::DefWithBodyId(self.def);
494         for item in block.items() {
495             let def: ModuleDefId = match item {
496                 ast::ModuleItem::FnDef(def) => {
497                     let ast_id = self.expander.ast_id(&def);
498                     FunctionLoc { container: container.into(), ast_id }.intern(self.db).into()
499                 }
500                 ast::ModuleItem::StructDef(def) => {
501                     let ast_id = self.expander.ast_id(&def);
502                     StructLoc { container, ast_id }.intern(self.db).into()
503                 }
504                 ast::ModuleItem::EnumDef(def) => {
505                     let ast_id = self.expander.ast_id(&def);
506                     EnumLoc { container, ast_id }.intern(self.db).into()
507                 }
508                 ast::ModuleItem::UnionDef(def) => {
509                     let ast_id = self.expander.ast_id(&def);
510                     UnionLoc { container, ast_id }.intern(self.db).into()
511                 }
512                 _ => continue,
513             };
514             self.body.defs.push(def)
515         }
516     }
517
518     fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
519         if let Some(block) = expr {
520             self.collect_block(block)
521         } else {
522             self.missing_expr()
523         }
524     }
525
526     fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
527         let pattern = match &pat {
528             ast::Pat::BindPat(bp) => {
529                 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
530                 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
531                 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
532                 Pat::Bind { name, mode: annotation, subpat }
533             }
534             ast::Pat::TupleStructPat(p) => {
535                 let path = p.path().and_then(|path| self.expander.parse_path(path));
536                 let args = p.args().map(|p| self.collect_pat(p)).collect();
537                 Pat::TupleStruct { path, args }
538             }
539             ast::Pat::RefPat(p) => {
540                 let pat = self.collect_pat_opt(p.pat());
541                 let mutability = Mutability::from_mutable(p.is_mut());
542                 Pat::Ref { pat, mutability }
543             }
544             ast::Pat::PathPat(p) => {
545                 let path = p.path().and_then(|path| self.expander.parse_path(path));
546                 path.map(Pat::Path).unwrap_or(Pat::Missing)
547             }
548             ast::Pat::TuplePat(p) => {
549                 let args = p.args().map(|p| self.collect_pat(p)).collect();
550                 Pat::Tuple(args)
551             }
552             ast::Pat::PlaceholderPat(_) => Pat::Wild,
553             ast::Pat::RecordPat(p) => {
554                 let path = p.path().and_then(|path| self.expander.parse_path(path));
555                 let record_field_pat_list =
556                     p.record_field_pat_list().expect("every struct should have a field list");
557                 let mut fields: Vec<_> = record_field_pat_list
558                     .bind_pats()
559                     .filter_map(|bind_pat| {
560                         let ast_pat =
561                             ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
562                         let pat = self.collect_pat(ast_pat);
563                         let name = bind_pat.name()?.as_name();
564                         Some(RecordFieldPat { name, pat })
565                     })
566                     .collect();
567                 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
568                     let ast_pat = f.pat()?;
569                     let pat = self.collect_pat(ast_pat);
570                     let name = f.name()?.as_name();
571                     Some(RecordFieldPat { name, pat })
572                 });
573                 fields.extend(iter);
574
575                 Pat::Record { path, args: fields }
576             }
577
578             // FIXME: implement
579             ast::Pat::DotDotPat(_) => Pat::Missing,
580             ast::Pat::BoxPat(_) => Pat::Missing,
581             ast::Pat::LiteralPat(_) => Pat::Missing,
582             ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
583         };
584         let ptr = AstPtr::new(&pat);
585         self.alloc_pat(pattern, Either::Left(ptr))
586     }
587
588     fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
589         if let Some(pat) = pat {
590             self.collect_pat(pat)
591         } else {
592             self.missing_pat()
593         }
594     }
595 }
596
597 impl From<ast::BinOp> for BinaryOp {
598     fn from(ast_op: ast::BinOp) -> Self {
599         match ast_op {
600             ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
601             ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
602             ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
603             ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
604             ast::BinOp::LesserEqualTest => {
605                 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
606             }
607             ast::BinOp::GreaterEqualTest => {
608                 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
609             }
610             ast::BinOp::LesserTest => {
611                 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
612             }
613             ast::BinOp::GreaterTest => {
614                 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
615             }
616             ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
617             ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
618             ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
619             ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
620             ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
621             ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
622             ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
623             ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
624             ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
625             ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
626             ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
627             ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
628             ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) },
629             ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
630             ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
631             ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
632             ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
633             ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
634             ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
635             ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
636             ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
637         }
638     }
639 }