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) => {
|
pat_enum(_, args) => {
|
||||||
match cx.tcx.def_map.get(&pat_id) {
|
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 => {
|
def_variant(_, id) if variant(id) == ctor_id => {
|
||||||
let args = match args {
|
let args = match args {
|
||||||
Some(args) => args,
|
Some(args) => args,
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
|
use metadata::csearch;
|
||||||
|
use middle::astencode;
|
||||||
use middle::resolve;
|
use middle::resolve;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle;
|
use middle;
|
||||||
|
@ -19,6 +21,8 @@ use core::vec;
|
||||||
use syntax::{ast, ast_map, ast_util, visit};
|
use syntax::{ast, ast_map, ast_util, visit};
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
|
|
||||||
|
use std::oldmap::HashMap;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This pass classifies expressions by their constant-ness.
|
// This pass classifies expressions by their constant-ness.
|
||||||
//
|
//
|
||||||
|
@ -187,7 +191,24 @@ pub fn lookup_const_by_id(tcx: ty::ctxt,
|
||||||
Some(_) => None
|
Some(_) => None
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
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(
|
self.tcx.sess.span_bug(
|
||||||
pat.span,
|
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 {
|
pub fn pat_is_const(dm: resolve::DefMap, pat: &pat) -> bool {
|
||||||
match pat.node {
|
match pat.node {
|
||||||
pat_ident(_, _, None) => {
|
pat_ident(_, _, None) | pat_enum(*) => {
|
||||||
match dm.find(&pat.id) {
|
match dm.find(&pat.id) {
|
||||||
Some(def_const(*)) => true,
|
Some(def_const(*)) => true,
|
||||||
_ => false
|
_ => false
|
||||||
|
|
|
@ -4333,23 +4333,24 @@ pub impl Resolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
pat_enum(path, _) => {
|
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) {
|
match self.resolve_path(path, ValueNS, false, visitor) {
|
||||||
Some(def @ def_variant(*)) |
|
Some(def @ def_variant(*)) |
|
||||||
Some(def @ def_struct(*)) => {
|
Some(def @ def_struct(*)) |
|
||||||
|
Some(def @ def_const(*)) => {
|
||||||
self.record_def(pattern.id, def);
|
self.record_def(pattern.id, def);
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
self.session.span_err(
|
self.session.span_err(
|
||||||
path.span,
|
path.span,
|
||||||
fmt!("not an enum variant or struct: %s",
|
fmt!("not an enum variant, struct or const: %s",
|
||||||
*self.session.str_of(
|
*self.session.str_of(
|
||||||
*path.idents.last())));
|
*path.idents.last())));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.session.span_err(path.span,
|
self.session.span_err(path.span,
|
||||||
~"unresolved enum variant \
|
~"unresolved enum variant, \
|
||||||
or struct");
|
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()};
|
let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
|
||||||
do enter_match(bcx, tcx.def_map, m, col, val) |p| {
|
do enter_match(bcx, tcx.def_map, m, col, val) |p| {
|
||||||
match p.node {
|
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) => {
|
ast::pat_enum(_, ref subpats) => {
|
||||||
if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
|
if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
|
||||||
match *subpats {
|
match *subpats {
|
||||||
|
@ -520,15 +530,6 @@ pub fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
|
||||||
None
|
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) => {
|
ast::pat_lit(l) => {
|
||||||
if opt_eq(tcx, &lit(ExprLit(l)), opt) {Some(~[])} else {None}
|
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,
|
add_to_set(ccx.tcx, &mut found,
|
||||||
variant_opt(bcx, cur.id));
|
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.
|
// 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);
|
fcx.write_ty(pat.id, b_ty);
|
||||||
}
|
}
|
||||||
|
ast::pat_enum(*) |
|
||||||
ast::pat_ident(*) if pat_is_const(tcx.def_map, pat) => {
|
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_did = ast_util::def_id_of_def(tcx.def_map.get(&pat.id));
|
||||||
let const_tpt = ty::lookup_item_type(tcx, const_did);
|
let const_tpt = ty::lookup_item_type(tcx, const_did);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue