Skip to content

Commit 56d288d

Browse files
committed
auto merge of #5464 : luqmana/rust/const-pat, r=pcwalton
r? @pcwalton
2 parents efb5f87 + 3f2d576 commit 56d288d

File tree

8 files changed

+93
-16
lines changed

8 files changed

+93
-16
lines changed

src/librustc/middle/check_match.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,25 @@ pub fn specialize(cx: @MatchCheckCtxt,
528528
}
529529
pat_enum(_, args) => {
530530
match cx.tcx.def_map.get(&pat_id) {
531+
def_const(did) => {
532+
let const_expr =
533+
lookup_const_by_id(cx.tcx, did).get();
534+
let e_v = eval_const_expr(cx.tcx, const_expr);
535+
let match_ = match ctor_id {
536+
val(ref v) => compare_const_vals(e_v, (*v)) == 0,
537+
range(ref c_lo, ref c_hi) => {
538+
compare_const_vals((*c_lo), e_v) >= 0 &&
539+
compare_const_vals((*c_hi), e_v) <= 0
540+
}
541+
single => true,
542+
_ => fail!(~"type error")
543+
};
544+
if match_ {
545+
Some(vec::from_slice(r.tail()))
546+
} else {
547+
None
548+
}
549+
}
531550
def_variant(_, id) if variant(id) == ctor_id => {
532551
let args = match args {
533552
Some(args) => args,

src/librustc/middle/const_eval.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
use core::prelude::*;
1212

13+
use metadata::csearch;
14+
use middle::astencode;
1315
use middle::resolve;
1416
use middle::ty;
1517
use middle;
@@ -19,6 +21,8 @@ use core::vec;
1921
use syntax::{ast, ast_map, ast_util, visit};
2022
use syntax::ast::*;
2123

24+
use std::oldmap::HashMap;
25+
2226
//
2327
// This pass classifies expressions by their constant-ness.
2428
//
@@ -187,7 +191,24 @@ pub fn lookup_const_by_id(tcx: ty::ctxt,
187191
Some(_) => None
188192
}
189193
} else {
190-
None
194+
let maps = astencode::Maps {
195+
mutbl_map: HashMap(),
196+
root_map: HashMap(),
197+
last_use_map: HashMap(),
198+
method_map: HashMap(),
199+
vtable_map: HashMap(),
200+
write_guard_map: HashMap(),
201+
moves_map: HashMap(),
202+
capture_map: HashMap()
203+
};
204+
match csearch::maybe_get_item_ast(tcx, def_id,
205+
|a, b, c, d| astencode::decode_inlined_item(a, b, maps, /*bar*/ copy c, d)) {
206+
csearch::found(ast::ii_item(item)) => match item.node {
207+
item_const(_, const_expr) => Some(const_expr),
208+
_ => None
209+
},
210+
_ => None
211+
}
191212
}
192213
}
193214

src/librustc/middle/mem_categorization.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,11 @@ pub impl mem_categorization_ctxt {
916916
self.cat_pattern(cmt_field, *subpat, op);
917917
}
918918
}
919+
Some(ast::def_const(*)) => {
920+
for subpats.each |subpat| {
921+
self.cat_pattern(cmt, *subpat, op);
922+
}
923+
}
919924
_ => {
920925
self.tcx.sess.span_bug(
921926
pat.span,

src/librustc/middle/pat_util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: @pat) -> bool {
4343

4444
pub fn pat_is_const(dm: resolve::DefMap, pat: &pat) -> bool {
4545
match pat.node {
46-
pat_ident(_, _, None) => {
46+
pat_ident(_, _, None) | pat_enum(*) => {
4747
match dm.find(&pat.id) {
4848
Some(def_const(*)) => true,
4949
_ => false

src/librustc/middle/resolve.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4333,23 +4333,24 @@ pub impl Resolver {
43334333
}
43344334

43354335
pat_enum(path, _) => {
4336-
// This must be an enum variant or struct.
4336+
// This must be an enum variant, struct or const.
43374337
match self.resolve_path(path, ValueNS, false, visitor) {
43384338
Some(def @ def_variant(*)) |
4339-
Some(def @ def_struct(*)) => {
4339+
Some(def @ def_struct(*)) |
4340+
Some(def @ def_const(*)) => {
43404341
self.record_def(pattern.id, def);
43414342
}
43424343
Some(_) => {
43434344
self.session.span_err(
43444345
path.span,
4345-
fmt!("not an enum variant or struct: %s",
4346+
fmt!("not an enum variant, struct or const: %s",
43464347
*self.session.str_of(
43474348
*path.idents.last())));
43484349
}
43494350
None => {
43504351
self.session.span_err(path.span,
4351-
~"unresolved enum variant \
4352-
or struct");
4352+
~"unresolved enum variant, \
4353+
struct or const");
43534354
}
43544355
}
43554356

src/librustc/middle/trans/_match.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,16 @@ pub fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
502502
let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
503503
do enter_match(bcx, tcx.def_map, m, col, val) |p| {
504504
match p.node {
505+
ast::pat_enum(*) |
506+
ast::pat_ident(_, _, None) if pat_is_const(tcx.def_map, p) => {
507+
let const_def = tcx.def_map.get(&p.id);
508+
let const_def_id = ast_util::def_id_of_def(const_def);
509+
if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
510+
Some(~[])
511+
} else {
512+
None
513+
}
514+
}
505515
ast::pat_enum(_, ref subpats) => {
506516
if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
507517
match *subpats {
@@ -520,15 +530,6 @@ pub fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
520530
None
521531
}
522532
}
523-
ast::pat_ident(_, _, None) if pat_is_const(tcx.def_map, p) => {
524-
let const_def = tcx.def_map.get(&p.id);
525-
let const_def_id = ast_util::def_id_of_def(const_def);
526-
if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
527-
Some(~[])
528-
} else {
529-
None
530-
}
531-
}
532533
ast::pat_lit(l) => {
533534
if opt_eq(tcx, &lit(ExprLit(l)), opt) {Some(~[])} else {None}
534535
}
@@ -806,6 +807,10 @@ pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[Opt] {
806807
add_to_set(ccx.tcx, &mut found,
807808
variant_opt(bcx, cur.id));
808809
}
810+
Some(ast::def_const(const_did)) => {
811+
add_to_set(ccx.tcx, &mut found,
812+
lit(ConstLit(const_did)));
813+
}
809814
_ => {}
810815
}
811816
}
@@ -1782,6 +1787,9 @@ pub fn bind_irrefutable_pat(bcx: block,
17821787
}
17831788
}
17841789
}
1790+
Some(ast::def_const(*)) => {
1791+
bcx = bind_irrefutable_pat(bcx, pat, val, make_copy, binding_mode);
1792+
}
17851793
_ => {
17861794
// Nothing to do here.
17871795
}

src/librustc/middle/typeck/check/_match.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ pub fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
366366
}
367367
fcx.write_ty(pat.id, b_ty);
368368
}
369+
ast::pat_enum(*) |
369370
ast::pat_ident(*) if pat_is_const(tcx.def_map, pat) => {
370371
let const_did = ast_util::def_id_of_def(tcx.def_map.get(&pat.id));
371372
let const_tpt = ty::lookup_item_type(tcx, const_did);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-fast
12+
// aux-build:cci_const.rs
13+
14+
extern mod cci_const;
15+
16+
fn main() {
17+
let x = cci_const::uint_val;
18+
match x {
19+
cci_const::uint_val => {}
20+
_ => {}
21+
}
22+
}

0 commit comments

Comments
 (0)