Skip to content

Commit 2b01ef3

Browse files
committed
Make the default branch checking more general
for match expressions to address comments.
1 parent 6869645 commit 2b01ef3

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

src/librustc/middle/check_match.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
4343
span: DUMMY_SP
4444
};
4545

46-
struct Matrix<'a>(Vec<Vec<&'a Pat>>);
46+
pub struct Matrix<'a>(pub Vec<Vec<&'a Pat>>);
4747

4848
/// Pretty-printer for matrices of patterns, example:
4949
/// ++++++++++++++++++++++++++
@@ -120,14 +120,14 @@ pub enum Constructor {
120120
}
121121

122122
#[derive(Clone, PartialEq)]
123-
enum Usefulness {
123+
pub enum Usefulness {
124124
Useful,
125125
UsefulWithWitness(Vec<P<Pat>>),
126126
NotUseful
127127
}
128128

129129
#[derive(Copy)]
130-
enum WitnessPreference {
130+
pub enum WitnessPreference {
131131
ConstructWitness,
132132
LeaveOutWitness
133133
}
@@ -568,11 +568,10 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: Ty,
568568

569569
// Note: is_useful doesn't work on empty types, as the paper notes.
570570
// So it assumes that v is non-empty.
571-
fn is_useful(cx: &MatchCheckCtxt,
572-
matrix: &Matrix,
573-
v: &[&Pat],
574-
witness: WitnessPreference)
575-
-> Usefulness {
571+
pub fn is_useful(cx: &MatchCheckCtxt,
572+
matrix: &Matrix,
573+
v: &[&Pat],
574+
witness: WitnessPreference) -> Usefulness {
576575
let &Matrix(ref rows) = matrix;
577576
debug!("{:?}", matrix);
578577
if rows.len() == 0u {

src/librustc_trans/trans/_match.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ use self::FailureHandler::*;
191191
use back::abi;
192192
use llvm::{ValueRef, BasicBlockRef};
193193
use middle::check_match::StaticInliner;
194+
use middle::check_match::Usefulness::NotUseful;
195+
use middle::check_match::WitnessPreference::LeaveOutWitness;
194196
use middle::check_match;
195197
use middle::const_eval;
196198
use middle::def::{self, DefMap};
@@ -1398,14 +1400,27 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
13981400

13991401
// `compile_submatch` works one column of arm patterns a time and
14001402
// then peels that column off. So as we progress, it may become
1401-
// impossible to tell whether we have a genuine default arm, i.e.
1402-
// `_ => foo` or not. Sometimes it is important to know that in order
1403-
// to decide whether moving on to the next condition or falling back
1404-
// to the default arm.
1405-
let has_default = arms.last().map_or(false, |arm| {
1406-
arm.pats.len() == 1
1407-
&& arm.pats.last().unwrap().node == ast::PatWild(ast::PatWildSingle)
1408-
});
1403+
// impossible to tell whether we have a genuine default arm or not.
1404+
// Computing such property upfront, however, is straightforward -
1405+
// if the last arm of the match expression shadows a `PatWildSingle`,
1406+
// then it is a genuine default arm.
1407+
//
1408+
// Sometimes it is important to know that in order to decide whether
1409+
// moving on to the next arm or falling back to the default one.
1410+
let is_geniune_default = |&: pats: &Vec<P<ast::Pat>>| {
1411+
let mcx = check_match::MatchCheckCtxt {
1412+
tcx: tcx,
1413+
param_env: ty::empty_parameter_environment(tcx),
1414+
};
1415+
let ps = pats.iter().map(|p| &**p).collect();
1416+
let matrix = check_match::Matrix(vec![ps]);
1417+
let candidate = [check_match::DUMMY_WILD_PAT];
1418+
match check_match::is_useful(&mcx, &matrix, &candidate, LeaveOutWitness) {
1419+
NotUseful => true,
1420+
_ => false
1421+
}
1422+
};
1423+
let has_default = arm_pats.iter().last().map_or(false, is_geniune_default);
14091424

14101425
compile_submatch(bcx, &matches[], &[discr_datum.val], &chk, has_default);
14111426

0 commit comments

Comments
 (0)