librustc: Fix path-qualified and cross-crate constants in match patterns.
This commit is contained in:
parent
9814d0d412
commit
2ed80c35e2
7 changed files with 71 additions and 16 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue