Skip to content

Commit 26e692d

Browse files
author
Jakub Wieczorek
committed
Fix spurious non-exhaustive errors for cross-crate struct variants
1 parent f556c8c commit 26e692d

File tree

4 files changed

+40
-15
lines changed

4 files changed

+40
-15
lines changed

src/librustc/middle/check_match.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
194194
#[deriving(Clone, PartialEq)]
195195
enum ctor {
196196
single,
197-
variant(DefId /* variant */, bool /* is_structure */),
197+
variant(DefId),
198198
val(const_val),
199199
range(const_val, const_val),
200200
vec(uint)
@@ -218,7 +218,8 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &ctor, pats: Vec<Gc<Pat>>, lty:
218218

219219
ty::ty_enum(cid, _) | ty::ty_struct(cid, _) => {
220220
let (vid, is_structure) = match ctor {
221-
&variant(vid, is_structure) => (vid, is_structure),
221+
&variant(vid) => (vid,
222+
ty::enum_variant_with_id(cx.tcx, cid, vid).arg_names.is_some()),
222223
_ => (cid, true)
223224
};
224225
if is_structure {
@@ -310,7 +311,7 @@ fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor
310311
ty::ty_enum(eid, _) =>
311312
ty::enum_variants(cx.tcx, eid)
312313
.iter()
313-
.map(|va| variant(va.id, va.arg_names.is_some()))
314+
.map(|va| variant(va.id))
314315
.collect(),
315316

316317
ty::ty_vec(_, None) =>
@@ -434,7 +435,7 @@ fn pat_ctor_id(cx: &MatchCheckCtxt, left_ty: ty::t, p: Gc<Pat>) -> Option<ctor>
434435
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
435436
Some(val(eval_const_expr(cx.tcx, &*const_expr)))
436437
},
437-
Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)),
438+
Some(&DefVariant(_, id, _)) => Some(variant(id)),
438439
_ => None
439440
},
440441
PatEnum(..) =>
@@ -443,12 +444,12 @@ fn pat_ctor_id(cx: &MatchCheckCtxt, left_ty: ty::t, p: Gc<Pat>) -> Option<ctor>
443444
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
444445
Some(val(eval_const_expr(cx.tcx, &*const_expr)))
445446
},
446-
Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)),
447+
Some(&DefVariant(_, id, _)) => Some(variant(id)),
447448
_ => Some(single)
448449
},
449450
PatStruct(..) =>
450451
match cx.tcx.def_map.borrow().find(&pat.id) {
451-
Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)),
452+
Some(&DefVariant(_, id, _)) => Some(variant(id)),
452453
_ => Some(single)
453454
},
454455
PatLit(expr) =>
@@ -498,7 +499,7 @@ fn constructor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
498499
},
499500
ty::ty_enum(eid, _) => {
500501
match *ctor {
501-
variant(id, _) => enum_variant_with_id(cx.tcx, eid, id).args.len(),
502+
variant(id) => enum_variant_with_id(cx.tcx, eid, id).args.len(),
502503
_ => unreachable!()
503504
}
504505
}
@@ -545,9 +546,10 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
545546
&PatIdent(_, _, _) => {
546547
let opt_def = cx.tcx.def_map.borrow().find_copy(pat_id);
547548
match opt_def {
548-
Some(DefVariant(_, id, _)) => match *ctor_id {
549-
variant(vid, _) if vid == id => Some(vec!()),
550-
_ => None
549+
Some(DefVariant(_, id, _)) => if *ctor_id == variant(id) {
550+
Some(vec!())
551+
} else {
552+
None
551553
},
552554
Some(DefStatic(did, _)) => {
553555
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
@@ -581,7 +583,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
581583
}
582584
}
583585
}
584-
DefVariant(_, id, _) if variant(id, false) != *ctor_id => None,
586+
DefVariant(_, id, _) if *ctor_id != variant(id) => None,
585587
DefVariant(..) | DefFn(..) | DefStruct(..) => {
586588
Some(match args {
587589
&Some(ref args) => args.clone(),
@@ -596,7 +598,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
596598
// Is this a struct or an enum variant?
597599
let def = cx.tcx.def_map.borrow().get_copy(pat_id);
598600
let class_id = match def {
599-
DefVariant(_, variant_id, _) => if *ctor_id == variant(variant_id, true) {
601+
DefVariant(_, variant_id, _) => if *ctor_id == variant(variant_id) {
600602
Some(variant_id)
601603
} else {
602604
None

src/test/auxiliary/struct_variant_xc_aux.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@
1414
#![feature(struct_variant)]
1515

1616
pub enum Enum {
17-
Variant { pub arg: u8 }
17+
Variant(u8),
18+
StructVariant { pub arg: u8 }
1819
}

src/test/run-pass/struct_variant_xc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
// aux-build:struct_variant_xc_aux.rs
1212
extern crate struct_variant_xc_aux;
1313

14-
use struct_variant_xc_aux::Variant;
14+
use struct_variant_xc_aux::StructVariant;
1515

1616
pub fn main() {
17-
let _ = Variant { arg: 1 };
17+
let _ = StructVariant { arg: 1 };
1818
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2013-2014 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+
// aux-build:struct_variant_xc_aux.rs
12+
extern crate struct_variant_xc_aux;
13+
14+
use struct_variant_xc_aux::{StructVariant, Variant};
15+
16+
pub fn main() {
17+
let arg = match StructVariant { arg: 42 } {
18+
Variant(_) => unreachable!(),
19+
StructVariant { arg } => arg
20+
};
21+
assert_eq!(arg, 42);
22+
}

0 commit comments

Comments
 (0)