Skip to content

Commit 1320999

Browse files
committed
auto merge of #9747 : dim-an/rust/fix-match, r=alexcrichton
When `specialize`ing struct-like enum patterns, compare struct fields to pattern fields, not pattern fields to pattern fields. Closes #8351.
2 parents b17dc4a + da7f411 commit 1320999

File tree

3 files changed

+76
-27
lines changed

3 files changed

+76
-27
lines changed

src/librustc/middle/check_match.rs

+26-27
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use syntax::codemap::{Span, dummy_sp, Spanned};
2828
use syntax::visit;
2929
use syntax::visit::{Visitor,fn_kind};
3030

31-
pub struct MatchCheckCtxt {
31+
struct MatchCheckCtxt {
3232
tcx: ty::ctxt,
3333
method_map: method_map,
3434
moves_map: moves::MovesMap
@@ -64,7 +64,7 @@ pub fn check_crate(tcx: ty::ctxt,
6464
tcx.sess.abort_if_errors();
6565
}
6666

67-
pub fn check_expr(v: &mut CheckMatchVisitor,
67+
fn check_expr(v: &mut CheckMatchVisitor,
6868
cx: @MatchCheckCtxt,
6969
ex: @Expr,
7070
s: ()) {
@@ -115,7 +115,7 @@ pub fn check_expr(v: &mut CheckMatchVisitor,
115115
}
116116

117117
// Check for unreachable patterns
118-
pub fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
118+
fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
119119
let mut seen = ~[];
120120
for arm in arms.iter() {
121121
for pat in arm.pats.iter() {
@@ -154,14 +154,14 @@ pub fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
154154
}
155155
}
156156

157-
pub fn raw_pat(p: @Pat) -> @Pat {
157+
fn raw_pat(p: @Pat) -> @Pat {
158158
match p.node {
159159
PatIdent(_, _, Some(s)) => { raw_pat(s) }
160160
_ => { p }
161161
}
162162
}
163163

164-
pub fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, pats: ~[@Pat]) {
164+
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, pats: ~[@Pat]) {
165165
assert!((!pats.is_empty()));
166166
let ext = match is_useful(cx, &pats.map(|p| ~[*p]), [wild()]) {
167167
not_useful => {
@@ -209,12 +209,12 @@ pub fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, pats: ~[@Pat]) {
209209
cx.tcx.sess.span_err(sp, msg);
210210
}
211211

212-
pub type matrix = ~[~[@Pat]];
212+
type matrix = ~[~[@Pat]];
213213

214-
pub enum useful { useful(ty::t, ctor), useful_, not_useful }
214+
enum useful { useful(ty::t, ctor), useful_, not_useful }
215215

216216
#[deriving(Eq)]
217-
pub enum ctor {
217+
enum ctor {
218218
single,
219219
variant(DefId),
220220
val(const_val),
@@ -235,7 +235,7 @@ pub enum ctor {
235235

236236
// Note: is_useful doesn't work on empty types, as the paper notes.
237237
// So it assumes that v is non-empty.
238-
pub fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@Pat]) -> useful {
238+
fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@Pat]) -> useful {
239239
if m.len() == 0u { return useful_; }
240240
if m[0].len() == 0u { return not_useful; }
241241
let real_pat = match m.iter().find(|r| r[0].id != 0) {
@@ -314,7 +314,7 @@ pub fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@Pat]) -> useful {
314314
}
315315
}
316316

317-
pub fn is_useful_specialized(cx: &MatchCheckCtxt,
317+
fn is_useful_specialized(cx: &MatchCheckCtxt,
318318
m: &matrix,
319319
v: &[@Pat],
320320
ctor: ctor,
@@ -330,7 +330,7 @@ pub fn is_useful_specialized(cx: &MatchCheckCtxt,
330330
}
331331
}
332332

333-
pub fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option<ctor> {
333+
fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option<ctor> {
334334
let pat = raw_pat(p);
335335
match pat.node {
336336
PatWild => { None }
@@ -366,7 +366,7 @@ pub fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option<ctor> {
366366
}
367367
}
368368

369-
pub fn is_wild(cx: &MatchCheckCtxt, p: @Pat) -> bool {
369+
fn is_wild(cx: &MatchCheckCtxt, p: @Pat) -> bool {
370370
let pat = raw_pat(p);
371371
match pat.node {
372372
PatWild => { true }
@@ -380,7 +380,7 @@ pub fn is_wild(cx: &MatchCheckCtxt, p: @Pat) -> bool {
380380
}
381381
}
382382

383-
pub fn missing_ctor(cx: &MatchCheckCtxt,
383+
fn missing_ctor(cx: &MatchCheckCtxt,
384384
m: &matrix,
385385
left_ty: ty::t)
386386
-> Option<ctor> {
@@ -505,7 +505,7 @@ pub fn missing_ctor(cx: &MatchCheckCtxt,
505505
}
506506
}
507507

508-
pub fn ctor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
508+
fn ctor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
509509
match ty::get(ty).sty {
510510
ty::ty_tup(ref fs) => fs.len(),
511511
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) => 1u,
@@ -528,11 +528,11 @@ pub fn ctor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
528528
}
529529
}
530530

531-
pub fn wild() -> @Pat {
531+
fn wild() -> @Pat {
532532
@Pat {id: 0, node: PatWild, span: dummy_sp()}
533533
}
534534

535-
pub fn specialize(cx: &MatchCheckCtxt,
535+
fn specialize(cx: &MatchCheckCtxt,
536536
r: &[@Pat],
537537
ctor_id: &ctor,
538538
arity: uint,
@@ -662,15 +662,14 @@ pub fn specialize(cx: &MatchCheckCtxt,
662662
_ => None
663663
}
664664
}
665-
PatStruct(_, ref flds, _) => {
665+
PatStruct(_, ref pattern_fields, _) => {
666666
// Is this a struct or an enum variant?
667667
match cx.tcx.def_map.get_copy(&pat_id) {
668668
DefVariant(_, variant_id, _) => {
669669
if variant(variant_id) == *ctor_id {
670-
// FIXME #4731: Is this right? --pcw
671-
let args = flds.map(|ty_field| {
672-
match flds.iter().find(|f|
673-
f.ident == ty_field.ident) {
670+
let struct_fields = ty::lookup_struct_fields(cx.tcx, variant_id);
671+
let args = struct_fields.map(|sf| {
672+
match pattern_fields.iter().find(|f| f.ident.name == sf.name) {
674673
Some(f) => f.pat,
675674
_ => wild()
676675
}
@@ -700,7 +699,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
700699
}
701700
}
702701
let args = class_fields.iter().map(|class_field| {
703-
match flds.iter().find(|f|
702+
match pattern_fields.iter().find(|f|
704703
f.ident.name == class_field.name) {
705704
Some(f) => f.pat,
706705
_ => wild()
@@ -798,12 +797,12 @@ pub fn specialize(cx: &MatchCheckCtxt,
798797
}
799798
}
800799

801-
pub fn default(cx: &MatchCheckCtxt, r: &[@Pat]) -> Option<~[@Pat]> {
800+
fn default(cx: &MatchCheckCtxt, r: &[@Pat]) -> Option<~[@Pat]> {
802801
if is_wild(cx, r[0]) { Some(r.tail().to_owned()) }
803802
else { None }
804803
}
805804

806-
pub fn check_local(v: &mut CheckMatchVisitor,
805+
fn check_local(v: &mut CheckMatchVisitor,
807806
cx: &MatchCheckCtxt,
808807
loc: @Local,
809808
s: ()) {
@@ -817,7 +816,7 @@ pub fn check_local(v: &mut CheckMatchVisitor,
817816
check_legality_of_move_bindings(cx, false, [ loc.pat ]);
818817
}
819818

820-
pub fn check_fn(v: &mut CheckMatchVisitor,
819+
fn check_fn(v: &mut CheckMatchVisitor,
821820
cx: &MatchCheckCtxt,
822821
kind: &visit::fn_kind,
823822
decl: &fn_decl,
@@ -834,7 +833,7 @@ pub fn check_fn(v: &mut CheckMatchVisitor,
834833
}
835834
}
836835

837-
pub fn is_refutable(cx: &MatchCheckCtxt, pat: &Pat) -> bool {
836+
fn is_refutable(cx: &MatchCheckCtxt, pat: &Pat) -> bool {
838837
match cx.tcx.def_map.find(&pat.id) {
839838
Some(&DefVariant(enum_id, _, _)) => {
840839
if ty::enum_variants(cx.tcx, enum_id).len() != 1u {
@@ -872,7 +871,7 @@ pub fn is_refutable(cx: &MatchCheckCtxt, pat: &Pat) -> bool {
872871

873872
// Legality of move bindings checking
874873

875-
pub fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
874+
fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
876875
has_guard: bool,
877876
pats: &[@Pat]) {
878877
let tcx = cx.tcx;

src/test/run-pass/issue-8351-1.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
#[feature(struct_variant)];
12+
13+
enum E {
14+
Foo{f: int},
15+
Bar,
16+
}
17+
18+
pub fn main() {
19+
let e = Foo{f: 0};
20+
match e {
21+
Foo{f: 1} => fail2!(),
22+
Foo{_} => (),
23+
_ => fail2!(),
24+
}
25+
}

src/test/run-pass/issue-8351-2.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
#[feature(struct_variant)];
12+
13+
enum E {
14+
Foo{f: int, b: bool},
15+
Bar,
16+
}
17+
18+
pub fn main() {
19+
let e = Foo{f: 0, b: false};
20+
match e {
21+
Foo{f: 1, b: true} => fail2!(),
22+
Foo{b: false, f: 0} => (),
23+
_ => fail2!(),
24+
}
25+
}

0 commit comments

Comments
 (0)