From 26e692dd398da1608c6d8fc2c6f9ac34b7ea7a3a Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Sat, 21 Jun 2014 23:16:31 +0200 Subject: [PATCH] Fix spurious non-exhaustive errors for cross-crate struct variants --- src/librustc/middle/check_match.rs | 26 +++++++++++--------- src/test/auxiliary/struct_variant_xc_aux.rs | 3 ++- src/test/run-pass/struct_variant_xc.rs | 4 +-- src/test/run-pass/struct_variant_xc_match.rs | 22 +++++++++++++++++ 4 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 src/test/run-pass/struct_variant_xc_match.rs diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 6d8b178ba00..b550cb2bb68 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -194,7 +194,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) { #[deriving(Clone, PartialEq)] enum ctor { single, - variant(DefId /* variant */, bool /* is_structure */), + variant(DefId), val(const_val), range(const_val, const_val), vec(uint) @@ -218,7 +218,8 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &ctor, pats: Vec>, lty: ty::ty_enum(cid, _) | ty::ty_struct(cid, _) => { let (vid, is_structure) = match ctor { - &variant(vid, is_structure) => (vid, is_structure), + &variant(vid) => (vid, + ty::enum_variant_with_id(cx.tcx, cid, vid).arg_names.is_some()), _ => (cid, true) }; if is_structure { @@ -310,7 +311,7 @@ fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec ty::enum_variants(cx.tcx, eid) .iter() - .map(|va| variant(va.id, va.arg_names.is_some())) + .map(|va| variant(va.id)) .collect(), ty::ty_vec(_, None) => @@ -434,7 +435,7 @@ fn pat_ctor_id(cx: &MatchCheckCtxt, left_ty: ty::t, p: Gc) -> Option let const_expr = lookup_const_by_id(cx.tcx, did).unwrap(); Some(val(eval_const_expr(cx.tcx, &*const_expr))) }, - Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)), + Some(&DefVariant(_, id, _)) => Some(variant(id)), _ => None }, PatEnum(..) => @@ -443,12 +444,12 @@ fn pat_ctor_id(cx: &MatchCheckCtxt, left_ty: ty::t, p: Gc) -> Option let const_expr = lookup_const_by_id(cx.tcx, did).unwrap(); Some(val(eval_const_expr(cx.tcx, &*const_expr))) }, - Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)), + Some(&DefVariant(_, id, _)) => Some(variant(id)), _ => Some(single) }, PatStruct(..) => match cx.tcx.def_map.borrow().find(&pat.id) { - Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)), + Some(&DefVariant(_, id, _)) => Some(variant(id)), _ => Some(single) }, PatLit(expr) => @@ -498,7 +499,7 @@ fn constructor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint { }, ty::ty_enum(eid, _) => { match *ctor { - variant(id, _) => enum_variant_with_id(cx.tcx, eid, id).args.len(), + variant(id) => enum_variant_with_id(cx.tcx, eid, id).args.len(), _ => unreachable!() } } @@ -545,9 +546,10 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc], &PatIdent(_, _, _) => { let opt_def = cx.tcx.def_map.borrow().find_copy(pat_id); match opt_def { - Some(DefVariant(_, id, _)) => match *ctor_id { - variant(vid, _) if vid == id => Some(vec!()), - _ => None + Some(DefVariant(_, id, _)) => if *ctor_id == variant(id) { + Some(vec!()) + } else { + None }, Some(DefStatic(did, _)) => { let const_expr = lookup_const_by_id(cx.tcx, did).unwrap(); @@ -581,7 +583,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc], } } } - DefVariant(_, id, _) if variant(id, false) != *ctor_id => None, + DefVariant(_, id, _) if *ctor_id != variant(id) => None, DefVariant(..) | DefFn(..) | DefStruct(..) => { Some(match args { &Some(ref args) => args.clone(), @@ -596,7 +598,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc], // Is this a struct or an enum variant? let def = cx.tcx.def_map.borrow().get_copy(pat_id); let class_id = match def { - DefVariant(_, variant_id, _) => if *ctor_id == variant(variant_id, true) { + DefVariant(_, variant_id, _) => if *ctor_id == variant(variant_id) { Some(variant_id) } else { None diff --git a/src/test/auxiliary/struct_variant_xc_aux.rs b/src/test/auxiliary/struct_variant_xc_aux.rs index 1a756e432c3..88b6b363222 100644 --- a/src/test/auxiliary/struct_variant_xc_aux.rs +++ b/src/test/auxiliary/struct_variant_xc_aux.rs @@ -14,5 +14,6 @@ #![feature(struct_variant)] pub enum Enum { - Variant { pub arg: u8 } + Variant(u8), + StructVariant { pub arg: u8 } } diff --git a/src/test/run-pass/struct_variant_xc.rs b/src/test/run-pass/struct_variant_xc.rs index 8b1b91a32b6..11521e86117 100644 --- a/src/test/run-pass/struct_variant_xc.rs +++ b/src/test/run-pass/struct_variant_xc.rs @@ -11,8 +11,8 @@ // aux-build:struct_variant_xc_aux.rs extern crate struct_variant_xc_aux; -use struct_variant_xc_aux::Variant; +use struct_variant_xc_aux::StructVariant; pub fn main() { - let _ = Variant { arg: 1 }; + let _ = StructVariant { arg: 1 }; } diff --git a/src/test/run-pass/struct_variant_xc_match.rs b/src/test/run-pass/struct_variant_xc_match.rs new file mode 100644 index 00000000000..8cb1cdd2a7f --- /dev/null +++ b/src/test/run-pass/struct_variant_xc_match.rs @@ -0,0 +1,22 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:struct_variant_xc_aux.rs +extern crate struct_variant_xc_aux; + +use struct_variant_xc_aux::{StructVariant, Variant}; + +pub fn main() { + let arg = match StructVariant { arg: 42 } { + Variant(_) => unreachable!(), + StructVariant { arg } => arg + }; + assert_eq!(arg, 42); +}