librustc: Fix path-qualified and cross-crate constants in match patterns.

This commit is contained in:
Luqman Aden 2013-03-21 00:27:26 -07:00
parent 9814d0d412
commit 2ed80c35e2
7 changed files with 71 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 core::vec;
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 @@ pub impl mem_categorization_ctxt {
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 @@ pub impl Resolver {
}
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 @@ pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[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);