auto merge of #5464 : luqmana/rust/const-pat, r=pcwalton

r? @pcwalton
This commit is contained in:
bors 2013-03-21 08:49:13 -07:00
commit 56d288d0dc
8 changed files with 93 additions and 16 deletions

View File

@ -528,6 +528,25 @@ pub fn specialize(cx: @MatchCheckCtxt,
}
pat_enum(_, args) => {
match cx.tcx.def_map.get(&pat_id) {
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::from_slice(r.tail()))
} else {
None
}
}
def_variant(_, id) if variant(id) == ctor_id => {
let args = match args {
Some(args) => args,

View File

@ -10,6 +10,8 @@
use core::prelude::*;
use metadata::csearch;
use middle::astencode;
use middle::resolve;
use middle::ty;
use middle;
@ -19,6 +21,8 @@
use syntax::{ast, ast_map, ast_util, visit};
use syntax::ast::*;
use std::oldmap::HashMap;
//
// This pass classifies expressions by their constant-ness.
//
@ -187,7 +191,24 @@ pub fn lookup_const_by_id(tcx: ty::ctxt,
Some(_) => None
}
} else {
None
let maps = astencode::Maps {
mutbl_map: HashMap(),
root_map: HashMap(),
last_use_map: HashMap(),
method_map: HashMap(),
vtable_map: HashMap(),
write_guard_map: HashMap(),
moves_map: HashMap(),
capture_map: HashMap()
};
match csearch::maybe_get_item_ast(tcx, def_id,
|a, b, c, d| astencode::decode_inlined_item(a, b, maps, /*bar*/ copy c, d)) {
csearch::found(ast::ii_item(item)) => match item.node {
item_const(_, const_expr) => Some(const_expr),
_ => None
},
_ => None
}
}
}

View File

@ -916,6 +916,11 @@ fn cat_pattern(&self,
self.cat_pattern(cmt_field, *subpat, op);
}
}
Some(ast::def_const(*)) => {
for subpats.each |subpat| {
self.cat_pattern(cmt, *subpat, op);
}
}
_ => {
self.tcx.sess.span_bug(
pat.span,

View File

@ -43,7 +43,7 @@ pub fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: @pat) -> bool {
pub fn pat_is_const(dm: resolve::DefMap, pat: &pat) -> bool {
match pat.node {
pat_ident(_, _, None) => {
pat_ident(_, _, None) | pat_enum(*) => {
match dm.find(&pat.id) {
Some(def_const(*)) => true,
_ => false

View File

@ -4333,23 +4333,24 @@ struct in scope",
}
pat_enum(path, _) => {
// This must be an enum variant or struct.
// This must be an enum variant, struct or const.
match self.resolve_path(path, ValueNS, false, visitor) {
Some(def @ def_variant(*)) |
Some(def @ def_struct(*)) => {
Some(def @ def_struct(*)) |
Some(def @ def_const(*)) => {
self.record_def(pattern.id, def);
}
Some(_) => {
self.session.span_err(
path.span,
fmt!("not an enum variant or struct: %s",
fmt!("not an enum variant, struct or const: %s",
*self.session.str_of(
*path.idents.last())));
}
None => {
self.session.span_err(path.span,
~"unresolved enum variant \
or struct");
~"unresolved enum variant, \
struct or const");
}
}

View File

@ -502,6 +502,16 @@ pub fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
do enter_match(bcx, tcx.def_map, m, col, val) |p| {
match p.node {
ast::pat_enum(*) |
ast::pat_ident(_, _, None) if pat_is_const(tcx.def_map, p) => {
let const_def = tcx.def_map.get(&p.id);
let const_def_id = ast_util::def_id_of_def(const_def);
if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
Some(~[])
} else {
None
}
}
ast::pat_enum(_, ref subpats) => {
if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
match *subpats {
@ -520,15 +530,6 @@ pub fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
None
}
}
ast::pat_ident(_, _, None) if pat_is_const(tcx.def_map, p) => {
let const_def = tcx.def_map.get(&p.id);
let const_def_id = ast_util::def_id_of_def(const_def);
if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
Some(~[])
} else {
None
}
}
ast::pat_lit(l) => {
if opt_eq(tcx, &lit(ExprLit(l)), opt) {Some(~[])} else {None}
}
@ -806,6 +807,10 @@ fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], +val: Opt) {
add_to_set(ccx.tcx, &mut found,
variant_opt(bcx, cur.id));
}
Some(ast::def_const(const_did)) => {
add_to_set(ccx.tcx, &mut found,
lit(ConstLit(const_did)));
}
_ => {}
}
}
@ -1782,6 +1787,9 @@ pub fn bind_irrefutable_pat(bcx: block,
}
}
}
Some(ast::def_const(*)) => {
bcx = bind_irrefutable_pat(bcx, pat, val, make_copy, binding_mode);
}
_ => {
// Nothing to do here.
}

View File

@ -366,6 +366,7 @@ pub fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
}
fcx.write_ty(pat.id, b_ty);
}
ast::pat_enum(*) |
ast::pat_ident(*) if pat_is_const(tcx.def_map, pat) => {
let const_did = ast_util::def_id_of_def(tcx.def_map.get(&pat.id));
let const_tpt = ty::lookup_item_type(tcx, const_did);

View File

@ -0,0 +1,22 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-fast
// aux-build:cci_const.rs
extern mod cci_const;
fn main() {
let x = cci_const::uint_val;
match x {
cci_const::uint_val => {}
_ => {}
}
}