about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-02-03 16:38:48 -0500
committerNiko Matsakis <niko@alum.mit.edu>2016-03-25 06:44:14 -0400
commit5bc286806023ef4d63bceec4ba703399ba9ee2f7 (patch)
tree17d96f6670588cb33d06577867214d2ff8697fb5
parent40deb279a87e640f799140e9f19b3e64623c30da (diff)
downloadrust-5bc286806023ef4d63bceec4ba703399ba9ee2f7.tar.gz
rust-5bc286806023ef4d63bceec4ba703399ba9ee2f7.zip
make `const_expr_to_pat` fallible (but never have it actually fail)
-rw-r--r--src/librustc/middle/check_match.rs26
-rw-r--r--src/librustc/middle/const_eval.rs40
-rw-r--r--src/librustc_mir/hair/cx/pattern.rs12
3 files changed, 52 insertions, 26 deletions
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index b5e1d589996..77b09958278 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -478,15 +478,25 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
                     Some(Def::Const(did)) => {
                         let substs = Some(self.tcx.node_id_item_substs(pat.id).substs);
                         if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) {
-                            const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {
-
-                                if let Some(ref mut renaming_map) = self.renaming_map {
-                                    // Record any renamings we do here
-                                    record_renamings(const_expr, &pat, renaming_map);
+                            match const_expr_to_pat(self.tcx, const_expr, pat.span) {
+                                Ok(new_pat) => {
+                                    if let Some(ref mut map) = self.renaming_map {
+                                        // Record any renamings we do here
+                                        record_renamings(const_expr, &pat, map);
+                                    }
+                                    new_pat
                                 }
-
-                                new_pat
-                            })
+                                Err(def_id) => {
+                                    // TODO back-compat
+                                    self.failed = true;
+                                    self.tcx.sess.span_err(
+                                        pat.span,
+                                        &format!("constants of the type `{}` \
+                                                  cannot be used in patterns",
+                                                 self.tcx.item_path_str(def_id)));
+                                    pat
+                                }
+                            }
                         } else {
                             self.failed = true;
                             span_err!(self.tcx.sess, pat.span, E0158,
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index a8c2a73e72f..af1e9d60be4 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -323,10 +323,13 @@ impl ConstVal {
     }
 }
 
-pub fn const_expr_to_pat(tcx: &TyCtxt, expr: &Expr, span: Span) -> P<hir::Pat> {
+pub fn const_expr_to_pat(tcx: &ty::TyCtxt, expr: &Expr, span: Span)
+                         -> Result<P<hir::Pat>, DefId> {
     let pat = match expr.node {
         hir::ExprTup(ref exprs) =>
-            PatKind::Tup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &expr, span)).collect()),
+            PatKind::Tup(try!(exprs.iter()
+                                   .map(|expr| const_expr_to_pat(tcx, &expr, span))
+                                   .collect())),
 
         hir::ExprCall(ref callee, ref args) => {
             let def = *tcx.def_map.borrow().get(&callee.id).unwrap();
@@ -336,31 +339,38 @@ pub fn const_expr_to_pat(tcx: &TyCtxt, expr: &Expr, span: Span) -> P<hir::Pat> {
             let path = match def.full_def() {
                 Def::Struct(def_id) => def_to_path(tcx, def_id),
                 Def::Variant(_, variant_did) => def_to_path(tcx, variant_did),
-                Def::Fn(..) => return P(hir::Pat {
+                Def::Fn(..) => return Ok(P(hir::Pat {
                     id: expr.id,
                     node: PatKind::Lit(P(expr.clone())),
                     span: span,
-                }),
+                })),
                 _ => unreachable!()
             };
-            let pats = args.iter().map(|expr| const_expr_to_pat(tcx, &expr, span)).collect();
+            let pats = try!(args.iter()
+                                .map(|expr| const_expr_to_pat(tcx, &**expr, span))
+                                .collect());
             PatKind::TupleStruct(path, Some(pats))
         }
 
         hir::ExprStruct(ref path, ref fields, None) => {
-            let field_pats = fields.iter().map(|field| codemap::Spanned {
-                span: codemap::DUMMY_SP,
-                node: hir::FieldPat {
-                    name: field.name.node,
-                    pat: const_expr_to_pat(tcx, &field.expr, span),
-                    is_shorthand: false,
-                },
-            }).collect();
+            let field_pats =
+                try!(fields.iter()
+                           .map(|field| Ok(codemap::Spanned {
+                               span: codemap::DUMMY_SP,
+                               node: hir::FieldPat {
+                                   name: field.name.node,
+                                   pat: try!(const_expr_to_pat(tcx, &field.expr, span)),
+                                   is_shorthand: false,
+                               },
+                           }))
+                           .collect());
             PatKind::Struct(path.clone(), field_pats, false)
         }
 
         hir::ExprVec(ref exprs) => {
-            let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &expr, span)).collect();
+            let pats = try!(exprs.iter()
+                                 .map(|expr| const_expr_to_pat(tcx, &expr, span))
+                                 .collect());
             PatKind::Vec(pats, None, hir::HirVec::new())
         }
 
@@ -381,7 +391,7 @@ pub fn const_expr_to_pat(tcx: &TyCtxt, expr: &Expr, span: Span) -> P<hir::Pat> {
 
         _ => PatKind::Lit(P(expr.clone()))
     };
-    P(hir::Pat { id: expr.id, node: pat, span: span })
+    Ok(P(hir::Pat { id: expr.id, node: pat, span: span }))
 }
 
 pub fn eval_const_expr(tcx: &TyCtxt, e: &Expr) -> ConstVal {
diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs
index a9873778374..bfb8d1c401a 100644
--- a/src/librustc_mir/hair/cx/pattern.rs
+++ b/src/librustc_mir/hair/cx/pattern.rs
@@ -90,9 +90,15 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                         let substs = Some(self.cx.tcx.node_id_item_substs(pat.id).substs);
                         match const_eval::lookup_const_by_id(self.cx.tcx, def_id, substs) {
                             Some((const_expr, _const_ty)) => {
-                                let pat = const_eval::const_expr_to_pat(self.cx.tcx, const_expr,
-                                                                        pat.span);
-                                return self.to_pattern(&pat);
+                                match const_eval::const_expr_to_pat(self.cx.tcx,
+                                                                    const_expr,
+                                                                    pat.span) {
+                                    Ok(pat) =>
+                                        return self.to_pattern(&pat),
+                                    Err(_) =>
+                                        self.cx.tcx.sess.span_bug(
+                                            pat.span, "illegal constant"),
+                                }
                             }
                             None => {
                                 self.cx.tcx.sess.span_bug(