trans: overhaul match bindings. No more phi, one code path for guards.
Fixes #3256. Fixes #3291.
This commit is contained in:
parent
ff54ac8e59
commit
34bf0b9e97
@ -38,7 +38,7 @@ type config =
|
||||
uint_type: uint_ty,
|
||||
float_type: float_ty};
|
||||
|
||||
const ppregions: uint = 1 << 0;
|
||||
const verbose: uint = 1 << 0;
|
||||
const time_passes: uint = 1 << 1;
|
||||
const count_llvm_insns: uint = 1 << 2;
|
||||
const time_llvm_passes: uint = 1 << 3;
|
||||
@ -60,8 +60,7 @@ const meta_stats: uint = 1 << 16;
|
||||
const no_opt: uint = 1 << 17;
|
||||
|
||||
fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
|
||||
~[(~"ppregions", ~"prettyprint regions with \
|
||||
internal repr details", ppregions),
|
||||
~[(~"verbose", ~"in general, enable more debug printouts", verbose),
|
||||
(~"time-passes", ~"measure time of each rustc pass", time_passes),
|
||||
(~"count-llvm-insns", ~"count where LLVM \
|
||||
instrs originate", count_llvm_insns),
|
||||
@ -219,7 +218,7 @@ impl session {
|
||||
fn impossible_case(sp: span, msg: &str) -> ! {
|
||||
self.span_bug(sp, #fmt("Impossible case reached: %s", msg));
|
||||
}
|
||||
fn ppregions() -> bool { self.debugging_opt(ppregions) }
|
||||
fn verbose() -> bool { self.debugging_opt(verbose) }
|
||||
fn time_passes() -> bool { self.debugging_opt(time_passes) }
|
||||
fn count_llvm_insns() -> bool { self.debugging_opt(count_llvm_insns) }
|
||||
fn count_type_sizes() -> bool { self.debugging_opt(count_type_sizes) }
|
||||
|
@ -6,14 +6,14 @@ use syntax::fold::*;
|
||||
use syntax::codemap::span;
|
||||
use std::map::HashMap;
|
||||
|
||||
export pat_binding_ids, pat_bindings, pat_id_map;
|
||||
export pat_is_variant;
|
||||
export pat_binding_ids, pat_bindings, pat_id_map, PatIdMap;
|
||||
export pat_is_variant, pat_is_binding_or_wild;
|
||||
|
||||
type pat_id_map = std::map::HashMap<ident, node_id>;
|
||||
type PatIdMap = std::map::HashMap<ident, node_id>;
|
||||
|
||||
// This is used because same-named variables in alternative patterns need to
|
||||
// use the node_id of their namesake in the first pattern.
|
||||
fn pat_id_map(dm: resolve::DefMap, pat: @pat) -> pat_id_map {
|
||||
fn pat_id_map(dm: resolve::DefMap, pat: @pat) -> PatIdMap {
|
||||
let map = std::map::uint_hash();
|
||||
do pat_bindings(dm, pat) |_bm, p_id, _s, n| {
|
||||
map.insert(path_to_ident(n), p_id);
|
||||
@ -32,6 +32,14 @@ fn pat_is_variant(dm: resolve::DefMap, pat: @pat) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: @pat) -> bool {
|
||||
match pat.node {
|
||||
pat_ident(*) => !pat_is_variant(dm, pat),
|
||||
pat_wild => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_bindings(dm: resolve::DefMap, pat: @pat,
|
||||
it: fn(binding_mode, node_id, span, @path)) {
|
||||
do walk_pat(pat) |p| {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -49,7 +49,7 @@ use metadata::csearch;
|
||||
use driver::session::session;
|
||||
use util::common::may_break;
|
||||
use syntax::codemap::span;
|
||||
use pat_util::{pat_is_variant, pat_id_map};
|
||||
use pat_util::{pat_is_variant, pat_id_map, PatIdMap};
|
||||
use middle::ty;
|
||||
use middle::ty::{arg, field, node_type_table, mk_nil, ty_param_bounds_and_ty};
|
||||
use middle::ty::{vstore_uniq};
|
||||
|
@ -111,7 +111,7 @@ fn check_legality_of_move_bindings(fcx: @fn_ctxt,
|
||||
|
||||
type pat_ctxt = {
|
||||
fcx: @fn_ctxt,
|
||||
map: pat_id_map,
|
||||
map: PatIdMap,
|
||||
alt_region: ty::region, // Region for the alt as a whole
|
||||
block_region: ty::region, // Region for the block of the arm
|
||||
};
|
||||
|
@ -112,17 +112,17 @@ fn explain_region_and_span(cx: ctxt, region: ty::region)
|
||||
fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str {
|
||||
match br {
|
||||
br_named(id) => fmt!("&%s", cx.sess.str_of(id)),
|
||||
br_self if cx.sess.ppregions() => ~"&<self>",
|
||||
br_self if cx.sess.verbose() => ~"&<self>",
|
||||
br_self => ~"&self",
|
||||
|
||||
br_anon(idx) => {
|
||||
if cx.sess.ppregions() {fmt!("&%u", idx)} else {~"&"}
|
||||
if cx.sess.verbose() {fmt!("&%u", idx)} else {~"&"}
|
||||
}
|
||||
|
||||
// FIXME(#3011) -- even if this arm is removed, exhaustiveness checking
|
||||
// does not fail
|
||||
br_cap_avoid(id, br) => {
|
||||
if cx.sess.ppregions() {
|
||||
if cx.sess.verbose() {
|
||||
fmt!("br_cap_avoid(%?, %s)", id, bound_region_to_str(cx, *br))
|
||||
} else {
|
||||
bound_region_to_str(cx, *br)
|
||||
@ -175,7 +175,7 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str {
|
||||
// you should use `explain_region()` or, better yet,
|
||||
// `note_and_explain_region()`
|
||||
fn region_to_str(cx: ctxt, region: region) -> ~str {
|
||||
if cx.sess.ppregions() {
|
||||
if cx.sess.verbose() {
|
||||
return fmt!("&%?", region);
|
||||
}
|
||||
|
||||
|
9
src/test/run-pass/alt-ref-binding-in-guard-3256.rs
Normal file
9
src/test/run-pass/alt-ref-binding-in-guard-3256.rs
Normal file
@ -0,0 +1,9 @@
|
||||
fn main() {
|
||||
let x = Some(unsafe::exclusive(true));
|
||||
match move x {
|
||||
Some(ref z) if z.with(|b| *b) => {
|
||||
do z.with |b| { assert *b; }
|
||||
},
|
||||
_ => fail
|
||||
}
|
||||
}
|
14
src/test/run-pass/alt-value-binding-in-guard-3291.rs
Normal file
14
src/test/run-pass/alt-value-binding-in-guard-3291.rs
Normal file
@ -0,0 +1,14 @@
|
||||
fn foo(x: Option<~int>, b: bool) -> int {
|
||||
match x {
|
||||
None => { 1 }
|
||||
Some(copy x) if b => { *x }
|
||||
Some(_) => { 0 }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(Some(~22), true);
|
||||
foo(Some(~22), false);
|
||||
foo(None, true);
|
||||
foo(None, false);
|
||||
}
|
Loading…
Reference in New Issue
Block a user