]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/matches/mod.rs
Fix BTreeMap example typo
[rust.git] / src / librustc_mir / build / matches / mod.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Code related to match expresions. These are sufficiently complex
12 //! to warrant their own module and submodules. :) This main module
13 //! includes the high-level algorithm, the submodules contain the
14 //! details.
15
16 use build::{BlockAnd, BlockAndExtension, Builder};
17 use rustc_data_structures::fnv::FnvHashMap;
18 use rustc_data_structures::bitvec::BitVector;
19 use rustc::middle::const_val::ConstVal;
20 use rustc::ty::{AdtDef, Ty};
21 use rustc::mir::repr::*;
22 use hair::*;
23 use syntax::ast::{Name, NodeId};
24 use syntax::codemap::Span;
25
26 // helper functions, broken out by category:
27 mod simplify;
28 mod test;
29 mod util;
30
31 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
32     pub fn match_expr(&mut self,
33                       destination: &Lvalue<'tcx>,
34                       span: Span,
35                       mut block: BasicBlock,
36                       discriminant: ExprRef<'tcx>,
37                       arms: Vec<Arm<'tcx>>)
38                       -> BlockAnd<()> {
39         let discriminant_lvalue = unpack!(block = self.as_lvalue(block, discriminant));
40
41         let mut arm_blocks = ArmBlocks {
42             blocks: arms.iter()
43                         .map(|_| self.cfg.start_new_block())
44                         .collect(),
45         };
46
47         // Get the arm bodies and their scopes, while declaring bindings.
48         let arm_bodies: Vec<_> = arms.iter().map(|arm| {
49             let body = self.hir.mirror(arm.body.clone());
50             let scope = self.declare_bindings(None, body.span, &arm.patterns[0]);
51             (body, scope.unwrap_or(self.visibility_scope))
52         }).collect();
53
54         // assemble a list of candidates: there is one candidate per
55         // pattern, which means there may be more than one candidate
56         // *per arm*. These candidates are kept sorted such that the
57         // highest priority candidate comes first in the list.
58         // (i.e. same order as in source)
59         let candidates: Vec<_> =
60             arms.iter()
61                 .enumerate()
62                 .flat_map(|(arm_index, arm)| {
63                     arm.patterns.iter()
64                                 .map(move |pat| (arm_index, pat, arm.guard.clone()))
65                 })
66                 .map(|(arm_index, pattern, guard)| {
67                     Candidate {
68                         span: pattern.span,
69                         match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)],
70                         bindings: vec![],
71                         guard: guard,
72                         arm_index: arm_index,
73                     }
74                 })
75                 .collect();
76
77         // this will generate code to test discriminant_lvalue and
78         // branch to the appropriate arm block
79         let otherwise = self.match_candidates(span, &mut arm_blocks, candidates, block);
80
81         // because all matches are exhaustive, in principle we expect
82         // an empty vector to be returned here, but the algorithm is
83         // not entirely precise
84         if !otherwise.is_empty() {
85             let join_block = self.join_otherwise_blocks(span, otherwise);
86             self.panic(join_block, "something about matches algorithm not being precise", span);
87         }
88
89         // all the arm blocks will rejoin here
90         let end_block = self.cfg.start_new_block();
91
92         let outer_source_info = self.source_info(span);
93         for (arm_index, (body, visibility_scope)) in arm_bodies.into_iter().enumerate() {
94             let mut arm_block = arm_blocks.blocks[arm_index];
95             // Re-enter the visibility scope we created the bindings in.
96             self.visibility_scope = visibility_scope;
97             unpack!(arm_block = self.into(destination, arm_block, body));
98             self.cfg.terminate(arm_block, outer_source_info,
99                                TerminatorKind::Goto { target: end_block });
100         }
101         self.visibility_scope = outer_source_info.scope;
102
103         end_block.unit()
104     }
105
106     pub fn expr_into_pattern(&mut self,
107                              mut block: BasicBlock,
108                              irrefutable_pat: Pattern<'tcx>,
109                              initializer: ExprRef<'tcx>)
110                              -> BlockAnd<()> {
111         // optimize the case of `let x = ...`
112         match *irrefutable_pat.kind {
113             PatternKind::Binding { mode: BindingMode::ByValue,
114                                    var,
115                                    subpattern: None, .. } => {
116                 let lvalue = Lvalue::Var(self.var_indices[&var]);
117                 return self.into(&lvalue, block, initializer);
118             }
119             _ => {}
120         }
121         let lvalue = unpack!(block = self.as_lvalue(block, initializer));
122         self.lvalue_into_pattern(block,
123                                  irrefutable_pat,
124                                  &lvalue)
125     }
126
127     pub fn lvalue_into_pattern(&mut self,
128                                mut block: BasicBlock,
129                                irrefutable_pat: Pattern<'tcx>,
130                                initializer: &Lvalue<'tcx>)
131                                -> BlockAnd<()> {
132         // create a dummy candidate
133         let mut candidate = Candidate {
134             span: irrefutable_pat.span,
135             match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)],
136             bindings: vec![],
137             guard: None,
138             arm_index: 0, // since we don't call `match_candidates`, this field is unused
139         };
140
141         // Simplify the candidate. Since the pattern is irrefutable, this should
142         // always convert all match-pairs into bindings.
143         unpack!(block = self.simplify_candidate(block, &mut candidate));
144
145         if !candidate.match_pairs.is_empty() {
146             span_bug!(candidate.match_pairs[0].pattern.span,
147                       "match pairs {:?} remaining after simplifying \
148                        irrefutable pattern",
149                       candidate.match_pairs);
150         }
151
152         // now apply the bindings, which will also declare the variables
153         self.bind_matched_candidate(block, candidate.bindings);
154
155         block.unit()
156     }
157
158     /// Declares the bindings of the given pattern and returns the visibility scope
159     /// for the bindings in this patterns, if such a scope had to be created.
160     /// NOTE: Declaring the bindings should always be done in their drop scope.
161     pub fn declare_bindings(&mut self,
162                             mut var_scope: Option<VisibilityScope>,
163                             scope_span: Span,
164                             pattern: &Pattern<'tcx>)
165                             -> Option<VisibilityScope> {
166         match *pattern.kind {
167             PatternKind::Binding { mutability, name, mode: _, var, ty, ref subpattern } => {
168                 if var_scope.is_none() {
169                     var_scope = Some(self.new_visibility_scope(scope_span));
170                 }
171                 let source_info = SourceInfo {
172                     span: pattern.span,
173                     scope: var_scope.unwrap()
174                 };
175                 self.declare_binding(source_info, mutability, name, var, ty);
176                 if let Some(subpattern) = subpattern.as_ref() {
177                     var_scope = self.declare_bindings(var_scope, scope_span, subpattern);
178                 }
179             }
180             PatternKind::Array { ref prefix, ref slice, ref suffix } |
181             PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
182                 for subpattern in prefix.iter().chain(slice).chain(suffix) {
183                     var_scope = self.declare_bindings(var_scope, scope_span, subpattern);
184                 }
185             }
186             PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {
187             }
188             PatternKind::Deref { ref subpattern } => {
189                 var_scope = self.declare_bindings(var_scope, scope_span, subpattern);
190             }
191             PatternKind::Leaf { ref subpatterns } |
192             PatternKind::Variant { ref subpatterns, .. } => {
193                 for subpattern in subpatterns {
194                     var_scope = self.declare_bindings(var_scope, scope_span, &subpattern.pattern);
195                 }
196             }
197         }
198         var_scope
199     }
200 }
201
202 /// List of blocks for each arm (and potentially other metadata in the
203 /// future).
204 struct ArmBlocks {
205     blocks: Vec<BasicBlock>,
206 }
207
208 #[derive(Clone, Debug)]
209 pub struct Candidate<'pat, 'tcx:'pat> {
210     // span of the original pattern that gave rise to this candidate
211     span: Span,
212
213     // all of these must be satisfied...
214     match_pairs: Vec<MatchPair<'pat, 'tcx>>,
215
216     // ...these bindings established...
217     bindings: Vec<Binding<'tcx>>,
218
219     // ...and the guard must be evaluated...
220     guard: Option<ExprRef<'tcx>>,
221
222     // ...and then we branch to arm with this index.
223     arm_index: usize,
224 }
225
226 #[derive(Clone, Debug)]
227 struct Binding<'tcx> {
228     span: Span,
229     source: Lvalue<'tcx>,
230     name: Name,
231     var_id: NodeId,
232     var_ty: Ty<'tcx>,
233     mutability: Mutability,
234     binding_mode: BindingMode,
235 }
236
237 #[derive(Clone, Debug)]
238 pub struct MatchPair<'pat, 'tcx:'pat> {
239     // this lvalue...
240     lvalue: Lvalue<'tcx>,
241
242     // ... must match this pattern.
243     pattern: &'pat Pattern<'tcx>,
244
245     // HACK(eddyb) This is used to toggle whether a Slice pattern
246     // has had its length checked. This is only necessary because
247     // the "rest" part of the pattern right now has type &[T] and
248     // as such, it requires an Rvalue::Slice to be generated.
249     // See RFC 495 / issue #23121 for the eventual (proper) solution.
250     slice_len_checked: bool
251 }
252
253 #[derive(Clone, Debug, PartialEq)]
254 enum TestKind<'tcx> {
255     // test the branches of enum
256     Switch {
257         adt_def: AdtDef<'tcx>,
258         variants: BitVector,
259     },
260
261     // test the branches of enum
262     SwitchInt {
263         switch_ty: Ty<'tcx>,
264         options: Vec<ConstVal>,
265         indices: FnvHashMap<ConstVal, usize>,
266     },
267
268     // test for equality
269     Eq {
270         value: ConstVal,
271         ty: Ty<'tcx>,
272     },
273
274     // test whether the value falls within an inclusive range
275     Range {
276         lo: Literal<'tcx>,
277         hi: Literal<'tcx>,
278         ty: Ty<'tcx>,
279     },
280
281     // test length of the slice is equal to len
282     Len {
283         len: u64,
284         op: BinOp,
285     },
286 }
287
288 #[derive(Debug)]
289 pub struct Test<'tcx> {
290     span: Span,
291     kind: TestKind<'tcx>,
292 }
293
294 ///////////////////////////////////////////////////////////////////////////
295 // Main matching algorithm
296
297 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
298     /// The main match algorithm. It begins with a set of candidates
299     /// `candidates` and has the job of generating code to determine
300     /// which of these candidates, if any, is the correct one. The
301     /// candidates are sorted such that the first item in the list
302     /// has the highest priority. When a candidate is found to match
303     /// the value, we will generate a branch to the appropriate
304     /// block found in `arm_blocks`.
305     ///
306     /// The return value is a list of "otherwise" blocks. These are
307     /// points in execution where we found that *NONE* of the
308     /// candidates apply.  In principle, this means that the input
309     /// list was not exhaustive, though at present we sometimes are
310     /// not smart enough to recognize all exhaustive inputs.
311     ///
312     /// It might be surprising that the input can be inexhaustive.
313     /// Indeed, initially, it is not, because all matches are
314     /// exhaustive in Rust. But during processing we sometimes divide
315     /// up the list of candidates and recurse with a non-exhaustive
316     /// list. This is important to keep the size of the generated code
317     /// under control. See `test_candidates` for more details.
318     fn match_candidates<'pat>(&mut self,
319                               span: Span,
320                               arm_blocks: &mut ArmBlocks,
321                               mut candidates: Vec<Candidate<'pat, 'tcx>>,
322                               mut block: BasicBlock)
323                               -> Vec<BasicBlock>
324     {
325         debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})",
326                span, block, candidates);
327
328         // Start by simplifying candidates. Once this process is
329         // complete, all the match pairs which remain require some
330         // form of test, whether it be a switch or pattern comparison.
331         for candidate in &mut candidates {
332             unpack!(block = self.simplify_candidate(block, candidate));
333         }
334
335         // The candidates are sorted by priority. Check to see
336         // whether the higher priority candidates (and hence at
337         // the front of the vec) have satisfied all their match
338         // pairs.
339         let fully_matched =
340             candidates.iter().take_while(|c| c.match_pairs.is_empty()).count();
341         debug!("match_candidates: {:?} candidates fully matched", fully_matched);
342         let mut unmatched_candidates = candidates.split_off(fully_matched);
343         for candidate in candidates {
344             // If so, apply any bindings, test the guard (if any), and
345             // branch to the arm.
346             if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, candidate) {
347                 block = b;
348             } else {
349                 // if None is returned, then any remaining candidates
350                 // are unreachable (at least not through this path).
351                 return vec![];
352             }
353         }
354
355         // If there are no candidates that still need testing, we're done.
356         // Since all matches are exhaustive, execution should never reach this point.
357         if unmatched_candidates.is_empty() {
358             return vec![block];
359         }
360
361         // Test candidates where possible.
362         let (otherwise, tested_candidates) =
363             self.test_candidates(span, arm_blocks, &unmatched_candidates, block);
364
365         // If the target candidates were exhaustive, then we are done.
366         if otherwise.is_empty() {
367             return vec![];
368         }
369
370         // If all candidates were sorted into `target_candidates` somewhere, then
371         // the initial set was inexhaustive.
372         let untested_candidates = unmatched_candidates.split_off(tested_candidates);
373         if untested_candidates.len() == 0 {
374             return otherwise;
375         }
376
377         // Otherwise, let's process those remaining candidates.
378         let join_block = self.join_otherwise_blocks(span, otherwise);
379         self.match_candidates(span, arm_blocks, untested_candidates, join_block)
380     }
381
382     fn join_otherwise_blocks(&mut self,
383                              span: Span,
384                              mut otherwise: Vec<BasicBlock>)
385                              -> BasicBlock
386     {
387         let source_info = self.source_info(span);
388         otherwise.sort();
389         otherwise.dedup(); // variant switches can introduce duplicate target blocks
390         if otherwise.len() == 1 {
391             otherwise[0]
392         } else {
393             let join_block = self.cfg.start_new_block();
394             for block in otherwise {
395                 self.cfg.terminate(block, source_info,
396                                    TerminatorKind::Goto { target: join_block });
397             }
398             join_block
399         }
400     }
401
402     /// This is the most subtle part of the matching algorithm.  At
403     /// this point, the input candidates have been fully simplified,
404     /// and so we know that all remaining match-pairs require some
405     /// sort of test. To decide what test to do, we take the highest
406     /// priority candidate (last one in the list) and extract the
407     /// first match-pair from the list. From this we decide what kind
408     /// of test is needed using `test`, defined in the `test` module.
409     ///
410     /// *Note:* taking the first match pair is somewhat arbitrary, and
411     /// we might do better here by choosing more carefully what to
412     /// test.
413     ///
414     /// For example, consider the following possible match-pairs:
415     ///
416     /// 1. `x @ Some(P)` -- we will do a `Switch` to decide what variant `x` has
417     /// 2. `x @ 22` -- we will do a `SwitchInt`
418     /// 3. `x @ 3..5` -- we will do a range test
419     /// 4. etc.
420     ///
421     /// Once we know what sort of test we are going to perform, this
422     /// test may also help us with other candidates. So we walk over
423     /// the candidates (from high to low priority) and check. This
424     /// gives us, for each outcome of the test, a transformed list of
425     /// candidates.  For example, if we are testing the current
426     /// variant of `x.0`, and we have a candidate `{x.0 @ Some(v), x.1
427     /// @ 22}`, then we would have a resulting candidate of `{(x.0 as
428     /// Some).0 @ v, x.1 @ 22}`. Note that the first match-pair is now
429     /// simpler (and, in fact, irrefutable).
430     ///
431     /// But there may also be candidates that the test just doesn't
432     /// apply to. For example, consider the case of #29740:
433     ///
434     /// ```rust,ignore
435     /// match x {
436     ///     "foo" => ...,
437     ///     "bar" => ...,
438     ///     "baz" => ...,
439     ///     _ => ...,
440     /// }
441     /// ```
442     ///
443     /// Here the match-pair we are testing will be `x @ "foo"`, and we
444     /// will generate an `Eq` test. Because `"bar"` and `"baz"` are different
445     /// constants, we will decide that these later candidates are just not
446     /// informed by the eq test. So we'll wind up with three candidate sets:
447     ///
448     /// - If outcome is that `x == "foo"` (one candidate, derived from `x @ "foo"`)
449     /// - If outcome is that `x != "foo"` (empty list of candidates)
450     /// - Otherwise (three candidates, `x @ "bar"`, `x @ "baz"`, `x @
451     ///   _`). Here we have the invariant that everything in the
452     ///   otherwise list is of **lower priority** than the stuff in the
453     ///   other lists.
454     ///
455     /// So we'll compile the test. For each outcome of the test, we
456     /// recursively call `match_candidates` with the corresponding set
457     /// of candidates. But note that this set is now inexhaustive: for
458     /// example, in the case where the test returns false, there are
459     /// NO candidates, even though there is stll a value to be
460     /// matched. So we'll collect the return values from
461     /// `match_candidates`, which are the blocks where control-flow
462     /// goes if none of the candidates matched. At this point, we can
463     /// continue with the "otherwise" list.
464     ///
465     /// If you apply this to the above test, you basically wind up
466     /// with an if-else-if chain, testing each candidate in turn,
467     /// which is precisely what we want.
468     fn test_candidates<'pat>(&mut self,
469                              span: Span,
470                              arm_blocks: &mut ArmBlocks,
471                              candidates: &[Candidate<'pat, 'tcx>],
472                              block: BasicBlock)
473                              -> (Vec<BasicBlock>, usize)
474     {
475         // extract the match-pair from the highest priority candidate
476         let match_pair = &candidates.first().unwrap().match_pairs[0];
477         let mut test = self.test(match_pair);
478
479         // most of the time, the test to perform is simply a function
480         // of the main candidate; but for a test like SwitchInt, we
481         // may want to add cases based on the candidates that are
482         // available
483         match test.kind {
484             TestKind::SwitchInt { switch_ty, ref mut options, ref mut indices } => {
485                 for candidate in candidates.iter() {
486                     if !self.add_cases_to_switch(&match_pair.lvalue,
487                                                  candidate,
488                                                  switch_ty,
489                                                  options,
490                                                  indices) {
491                         break;
492                     }
493                 }
494             }
495             TestKind::Switch { adt_def: _, ref mut variants} => {
496                 for candidate in candidates.iter() {
497                     if !self.add_variants_to_switch(&match_pair.lvalue,
498                                                     candidate,
499                                                     variants) {
500                         break;
501                     }
502                 }
503             }
504             _ => { }
505         }
506
507         // perform the test, branching to one of N blocks. For each of
508         // those N possible outcomes, create a (initially empty)
509         // vector of candidates. Those are the candidates that still
510         // apply if the test has that particular outcome.
511         debug!("match_candidates: test={:?} match_pair={:?}", test, match_pair);
512         let target_blocks = self.perform_test(block, &match_pair.lvalue, &test);
513         let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect();
514
515         // Sort the candidates into the appropriate vector in
516         // `target_candidates`. Note that at some point we may
517         // encounter a candidate where the test is not relevant; at
518         // that point, we stop sorting.
519         let tested_candidates =
520             candidates.iter()
521                       .take_while(|c| self.sort_candidate(&match_pair.lvalue,
522                                                           &test,
523                                                           c,
524                                                           &mut target_candidates))
525                       .count();
526         assert!(tested_candidates > 0); // at least the last candidate ought to be tested
527         debug!("tested_candidates: {}", tested_candidates);
528         debug!("untested_candidates: {}", candidates.len() - tested_candidates);
529
530         // For each outcome of test, process the candidates that still
531         // apply. Collect a list of blocks where control flow will
532         // branch if one of the `target_candidate` sets is not
533         // exhaustive.
534         let otherwise: Vec<_> =
535             target_blocks.into_iter()
536                          .zip(target_candidates)
537                          .flat_map(|(target_block, target_candidates)| {
538                              self.match_candidates(span,
539                                                    arm_blocks,
540                                                    target_candidates,
541                                                    target_block)
542                          })
543                          .collect();
544
545         (otherwise, tested_candidates)
546     }
547
548     /// Initializes each of the bindings from the candidate by
549     /// moving/copying/ref'ing the source as appropriate. Tests the
550     /// guard, if any, and then branches to the arm. Returns the block
551     /// for the case where the guard fails.
552     ///
553     /// Note: we check earlier that if there is a guard, there cannot
554     /// be move bindings.  This isn't really important for the
555     /// self-consistency of this fn, but the reason for it should be
556     /// clear: after we've done the assignments, if there were move
557     /// bindings, further tests would be a use-after-move (which would
558     /// in turn be detected by the borrowck code that runs on the
559     /// MIR).
560     fn bind_and_guard_matched_candidate<'pat>(&mut self,
561                                               mut block: BasicBlock,
562                                               arm_blocks: &mut ArmBlocks,
563                                               candidate: Candidate<'pat, 'tcx>)
564                                               -> Option<BasicBlock> {
565         debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
566                block, candidate);
567
568         debug_assert!(candidate.match_pairs.is_empty());
569
570         self.bind_matched_candidate(block, candidate.bindings);
571
572         let arm_block = arm_blocks.blocks[candidate.arm_index];
573
574         if let Some(guard) = candidate.guard {
575             // the block to branch to if the guard fails; if there is no
576             // guard, this block is simply unreachable
577             let guard = self.hir.mirror(guard);
578             let source_info = self.source_info(guard.span);
579             let cond = unpack!(block = self.as_operand(block, guard));
580             let otherwise = self.cfg.start_new_block();
581             self.cfg.terminate(block, source_info,
582                                TerminatorKind::If { cond: cond,
583                                                     targets: (arm_block, otherwise)});
584             Some(otherwise)
585         } else {
586             let source_info = self.source_info(candidate.span);
587             self.cfg.terminate(block, source_info,
588                                TerminatorKind::Goto { target: arm_block });
589             None
590         }
591     }
592
593     fn bind_matched_candidate(&mut self,
594                               block: BasicBlock,
595                               bindings: Vec<Binding<'tcx>>) {
596         debug!("bind_matched_candidate(block={:?}, bindings={:?})",
597                block, bindings);
598
599         // Assign each of the bindings. This may trigger moves out of the candidate.
600         for binding in bindings {
601             // Find the variable for the `var_id` being bound. It
602             // should have been created by a previous call to
603             // `declare_bindings`.
604             let var_index = self.var_indices[&binding.var_id];
605
606             let rvalue = match binding.binding_mode {
607                 BindingMode::ByValue =>
608                     Rvalue::Use(Operand::Consume(binding.source)),
609                 BindingMode::ByRef(region, borrow_kind) =>
610                     Rvalue::Ref(region, borrow_kind, binding.source),
611             };
612
613             let source_info = self.source_info(binding.span);
614             self.cfg.push_assign(block, source_info,
615                                  &Lvalue::Var(var_index), rvalue);
616         }
617     }
618
619     fn declare_binding(&mut self,
620                        source_info: SourceInfo,
621                        mutability: Mutability,
622                        name: Name,
623                        var_id: NodeId,
624                        var_ty: Ty<'tcx>)
625                        -> u32
626     {
627         debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, source_info={:?})",
628                var_id, name, var_ty, source_info);
629
630         let index = self.var_decls.len();
631         self.var_decls.push(VarDecl::<'tcx> {
632             source_info: source_info,
633             mutability: mutability,
634             name: name,
635             ty: var_ty.clone(),
636         });
637         let index = index as u32;
638         let extent = self.extent_of_innermost_scope();
639         self.schedule_drop(source_info.span, extent, &Lvalue::Var(index), var_ty);
640         self.var_indices.insert(var_id, index);
641
642         debug!("declare_binding: index={:?}", index);
643
644         index
645     }
646 }