about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2013-01-24 20:10:05 -0800
committerTim Chevalier <chevalier@alum.wellesley.edu>2013-01-24 20:42:21 -0800
commitcff4f1476ee9b96433d7dfa23afe5d9fdd45b554 (patch)
treed6d4debfa8e7091f94819d95f69150f06a52f00c /src
parent2d33e308ac8bd4e59a54feaddf301488c215f90b (diff)
rustc: Less copy
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/check_match.rs287
1 files changed, 148 insertions, 139 deletions
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index aff19a5c37d..bd3b96d73eb 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -481,161 +481,170 @@ fn wild() -> @pat {
     @pat {id: 0, node: pat_wild, span: ast_util::dummy_sp()}
 }
 
-fn specialize(cx: @MatchCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint,
+fn specialize(cx: @MatchCheckCtxt, +r: ~[@pat], ctor_id: ctor, arity: uint,
               left_ty: ty::t) -> Option<~[@pat]> {
-    let r0 = raw_pat(r[0]);
-    match /*bad*/copy r0.node {
-      pat_wild => Some(vec::append(vec::from_elem(arity, wild()),
-                                   vec::tail(r))),
-      pat_ident(_, _, _) => {
-        match cx.tcx.def_map.find(r0.id) {
-          Some(def_variant(_, id)) => {
-            if variant(id) == ctor_id { Some(vec::tail(r)) }
-            else { None }
-          }
-          Some(def_const(did)) => {
-            let const_expr = lookup_const_by_id(cx.tcx, did).get();
-            let e_v = eval_const_expr(cx.tcx, const_expr);
-            let match_ = match ctor_id {
-                val(ref v) => compare_const_vals(e_v, (*v)) == 0,
-                range(ref c_lo, ref c_hi) => {
-                    compare_const_vals((*c_lo), e_v) >= 0 &&
-                        compare_const_vals((*c_hi), e_v) <= 0
+    // Sad, but I can't get rid of this easily
+    let mut r0 = copy *raw_pat(r[0]);
+    match r0 {
+        pat{id: pat_id, node: n, span: pat_span} =>
+            match n {
+            pat_wild => Some(vec::append(vec::from_elem(arity, wild()),
+                                         vec::tail(r))),
+            pat_ident(_, _, _) => {
+                match cx.tcx.def_map.find(pat_id) {
+                    Some(def_variant(_, id)) => {
+                        if variant(id) == ctor_id { Some(vec::tail(r)) }
+                        else { None }
+                    }
+                    Some(def_const(did)) => {
+                        let const_expr =
+                            lookup_const_by_id(cx.tcx, did).get();
+                        let e_v = eval_const_expr(cx.tcx, const_expr);
+                        let match_ = match ctor_id {
+                            val(ref v) => compare_const_vals(e_v, (*v)) == 0,
+                            range(ref c_lo, ref c_hi) => {
+                                compare_const_vals((*c_lo), e_v) >= 0 &&
+                                    compare_const_vals((*c_hi), e_v) <= 0
+                            }
+                            single => true,
+                            _ => fail ~"type error"
+                        };
+                        if match_ { Some(vec::tail(r)) } else { None }
+                    }
+                    _ => Some(vec::append(vec::from_elem(arity, wild()),
+                                          vec::tail(r)))
                 }
-                single => true,
-                _ => fail ~"type error"
-            };
-            if match_ { Some(vec::tail(r)) } else { None }
-          }
-          _ => Some(vec::append(vec::from_elem(arity, wild()), vec::tail(r)))
-        }
-      }
-      pat_enum(_, args) => {
-        match cx.tcx.def_map.get(r0.id) {
-          def_variant(_, id) if variant(id) == ctor_id => {
-            let args = match args {
-              Some(args) => args,
-              None => vec::from_elem(arity, wild())
-            };
-            Some(vec::append(args, vec::tail(r)))
-          }
-          def_variant(_, _) => None,
-          def_struct(*) => {
-            // XXX: Is this right? --pcw
-            let new_args;
-            match args {
-              Some(args) => new_args = args,
-              None => new_args = vec::from_elem(arity, wild())
-            }
-            Some(vec::append(new_args, vec::tail(r)))
-          }
-          _ => None
-        }
-      }
-      pat_rec(flds, _) => {
-        let ty_flds = match /*bad*/copy ty::get(left_ty).sty {
-            ty::ty_rec(flds) => flds,
-            _ => fail ~"bad type for pat_rec"
-        };
-        let args = vec::map(ty_flds, |ty_fld| {
-            match vec::find(flds, |f| f.ident == ty_fld.ident ) {
-              Some(f) => f.pat,
-              _ => wild()
             }
-        });
-        Some(vec::append(args, vec::tail(r)))
-      }
-      pat_struct(_, flds, _) => {
-        // Is this a struct or an enum variant?
-        match cx.tcx.def_map.get(r0.id) {
-            def_variant(_, variant_id) => {
-                if variant(variant_id) == ctor_id {
-                    // XXX: Is this right? --pcw
-                    let args = flds.map(|ty_field| {
-                        match vec::find(flds, |f| f.ident == ty_field.ident) {
-                            Some(f) => f.pat,
-                            _ => wild()
+            pat_enum(_, args) => {
+                match cx.tcx.def_map.get(pat_id) {
+                    def_variant(_, id) if variant(id) == ctor_id => {
+                        let args = match args {
+                            Some(args) => args,
+                            None => vec::from_elem(arity, wild())
+                        };
+                        Some(vec::append(args, vec::tail(r)))
+                    }
+                    def_variant(_, _) => None,
+                    def_struct(*) => {
+                        // XXX: Is this right? --pcw
+                        let new_args;
+                        match args {
+                            Some(args) => new_args = args,
+                            None => new_args = vec::from_elem(arity, wild())
                         }
-                    });
-                    Some(vec::append(args, vec::tail(r)))
-                } else {
-                    None
+                        Some(vec::append(new_args, vec::tail(r)))
+                    }
+                    _ => None
                 }
             }
-            _ => {
-                // Grab the class data that we care about.
-                let class_fields, class_id;
-                match ty::get(left_ty).sty {
-                    ty::ty_struct(cid, _) => {
-                        class_id = cid;
-                        class_fields = ty::lookup_struct_fields(cx.tcx,
-                                                               class_id);
+            pat_rec(ref flds, _) => {
+                let ty_flds = match /*bad*/copy ty::get(left_ty).sty {
+                    ty::ty_rec(flds) => flds,
+                    _ => fail ~"bad type for pat_rec"
+                };
+                let args = vec::map(ty_flds, |ty_fld| {
+                    match flds.find(|f| f.ident == ty_fld.ident) {
+                        Some(f) => f.pat,
+                        _ => wild()
+                    }
+                });
+                Some(vec::append(args, vec::tail(r)))
+            }
+            pat_struct(_, ref flds, _) => {
+                // Is this a struct or an enum variant?
+                match cx.tcx.def_map.get(pat_id) {
+                    def_variant(_, variant_id) => {
+                        if variant(variant_id) == ctor_id {
+                            // XXX: Is this right? --pcw
+                            let args = flds.map(|ty_field| {
+                                match flds.find(|f|
+                                                f.ident == ty_field.ident) {
+                                    Some(f) => f.pat,
+                                    _ => wild()
+                                }
+                            });
+                            Some(vec::append(args, vec::tail(r)))
+                        } else {
+                            None
+                        }
                     }
                     _ => {
-                        cx.tcx.sess.span_bug(r0.span, ~"struct pattern \
-                                                        didn't resolve to a \
-                                                        struct");
+                        // Grab the class data that we care about.
+                        let class_fields, class_id;
+                        match ty::get(left_ty).sty {
+                            ty::ty_struct(cid, _) => {
+                                class_id = cid;
+                                class_fields =
+                                    ty::lookup_struct_fields(cx.tcx,
+                                                             class_id);
+                            }
+                            _ => {
+                                cx.tcx.sess.span_bug(pat_span,
+                                ~"struct pattern didn't resolve to a struct");
+                            }
+                        }
+                        let args = vec::map(class_fields, |class_field| {
+                            match flds.find(|f|
+                                            f.ident == class_field.ident) {
+                                Some(f) => f.pat,
+                                _ => wild()
+                            }
+                        });
+                        Some(vec::append(args, vec::tail(r)))
                     }
                 }
-                let args = vec::map(class_fields, |class_field| {
-                    match vec::find(flds, |f| f.ident == class_field.ident ) {
-                      Some(f) => f.pat,
-                      _ => wild()
+            }
+            pat_tup(args) => Some(vec::append(args, vec::tail(r))),
+            pat_box(a) | pat_uniq(a) | pat_region(a) =>
+                Some(vec::append(~[a], vec::tail(r))),
+            pat_lit(expr) => {
+                let e_v = eval_const_expr(cx.tcx, expr);
+                let match_ = match ctor_id {
+                    val(ref v) => compare_const_vals(e_v, (*v)) == 0,
+                    range(ref c_lo, ref c_hi) => {
+                        compare_const_vals((*c_lo), e_v) >= 0 &&
+                            compare_const_vals((*c_hi), e_v) <= 0
                     }
-                });
-                Some(vec::append(args, vec::tail(r)))
+                    single => true,
+                    _ => fail ~"type error"
+                };
+                if match_ { Some(vec::tail(r)) } else { None }
             }
-        }
-      }
-      pat_tup(args) => Some(vec::append(args, vec::tail(r))),
-      pat_box(a) | pat_uniq(a) | pat_region(a) =>
-          Some(vec::append(~[a], vec::tail(r))),
-      pat_lit(expr) => {
-        let e_v = eval_const_expr(cx.tcx, expr);
-        let match_ = match ctor_id {
-          val(ref v) => compare_const_vals(e_v, (*v)) == 0,
-          range(ref c_lo, ref c_hi) => {
-            compare_const_vals((*c_lo), e_v) >= 0 &&
-                compare_const_vals((*c_hi), e_v) <= 0
-          }
-          single => true,
-          _ => fail ~"type error"
-        };
-        if match_ { Some(vec::tail(r)) } else { None }
-      }
-      pat_range(lo, hi) => {
-        let (c_lo, c_hi) = match ctor_id {
-          val(ref v) => ((/*bad*/copy *v), (/*bad*/copy *v)),
-          range(ref lo, ref hi) => ((/*bad*/copy *lo), (/*bad*/copy *hi)),
-          single => return Some(vec::tail(r)),
-          _ => fail ~"type error"
-        };
-        let v_lo = eval_const_expr(cx.tcx, lo),
-            v_hi = eval_const_expr(cx.tcx, hi);
-        let match_ = compare_const_vals(c_lo, v_lo) >= 0 &&
+            pat_range(lo, hi) => {
+                let (c_lo, c_hi) = match ctor_id {
+                    val(ref v) => ((/*bad*/copy *v), (/*bad*/copy *v)),
+                    range(ref lo, ref hi) =>
+                        ((/*bad*/copy *lo), (/*bad*/copy *hi)),
+                    single => return Some(vec::tail(r)),
+                    _ => fail ~"type error"
+                };
+                let v_lo = eval_const_expr(cx.tcx, lo),
+                v_hi = eval_const_expr(cx.tcx, hi);
+                let match_ = compare_const_vals(c_lo, v_lo) >= 0 &&
                     compare_const_vals(c_hi, v_hi) <= 0;
-        if match_ { Some(vec::tail(r)) } else { None }
+          if match_ { Some(vec::tail(r)) } else { None }
       }
-      pat_vec(elems, tail) => {
-        match ctor_id {
-          vec(_) => {
-            if elems.len() < arity && tail.is_some() {
-              // XXX: Bad copy.
-              Some(vec::append(
-                vec::append(copy elems, vec::from_elem(
-                    arity - elems.len(), wild()
-                )),
-                vec::tail(r)
-              ))
-            } else if elems.len() == arity {
-              Some(vec::append(elems, vec::tail(r)))
-            } else {
-              None
+            pat_vec(elems, tail) => {
+                match ctor_id {
+                    vec(_) => {
+                        let num_elements = elems.len();
+                        if num_elements < arity && tail.is_some() {
+                            Some(vec::append(
+                                vec::append(elems, vec::from_elem(
+                                    arity - num_elements, wild()
+                                )),
+                                vec::tail(r)
+                            ))
+                        } else if num_elements == arity {
+                            Some(vec::append(elems, vec::tail(r)))
+                        } else {
+                            None
+                        }
+                    }
+                    _ => None
+                }
             }
-          }
-          _ => None
         }
-      }
     }
 }