diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2016-02-03 16:38:48 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2016-03-25 06:44:14 -0400 |
| commit | 5bc286806023ef4d63bceec4ba703399ba9ee2f7 (patch) | |
| tree | 17d96f6670588cb33d06577867214d2ff8697fb5 | |
| parent | 40deb279a87e640f799140e9f19b3e64623c30da (diff) | |
| download | rust-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.rs | 26 | ||||
| -rw-r--r-- | src/librustc/middle/const_eval.rs | 40 | ||||
| -rw-r--r-- | src/librustc_mir/hair/cx/pattern.rs | 12 |
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( |
