auto merge of #8350 : dim-an/rust/fix-struct-match, r=pcwalton
Code that collects fields in struct-like patterns used to ignore wildcard patterns like `Foo{_}`. But `enter_defaults` considered struct-like patterns as default in order to overcome this (accoring to my understanding of situation). However such behaviour caused code like this: ``` enum E { Foo{f: int}, Bar } let e = Bar; match e { Foo{f: _f} => { /* do something (1) */ } _ => { /* do something (2) */ } } ``` consider pattern `Foo{f: _f}` as default. That caused inproper behaviour and even segfaults while trying to destruct `Bar` as `Foo{f: _f}`. Issues: #5625 , #5530. This patch fixes `collect_record_or_struct_fields` to split cases of single wildcard struct-like pattern and no struct-like pattern at all. Former case resolved with `enter_rec_or_struct` (and not with `enter_defaults`). Closes #5625. Closes #5530.
This commit is contained in:
commit
a931e04b75
@ -821,7 +821,8 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] {
|
||||
optmulti("", "cfg", "Configure the compilation
|
||||
environment", "SPEC"),
|
||||
optflag("", "emit-llvm",
|
||||
"Produce an LLVM bitcode file"),
|
||||
"Produce an LLVM assembly file if used with -S option;
|
||||
produce an LLVM bitcode file otherwise"),
|
||||
optflag("h", "help","Display this message"),
|
||||
optmulti("L", "", "Add a directory to the library search path",
|
||||
"PATH"),
|
||||
|
@ -183,7 +183,7 @@ use syntax::codemap::{span, dummy_sp};
|
||||
|
||||
// An option identifying a literal: either a unit-like struct or an
|
||||
// expression.
|
||||
pub enum Lit {
|
||||
enum Lit {
|
||||
UnitLikeStructLit(ast::NodeId), // the node ID of the pattern
|
||||
ExprLit(@ast::expr),
|
||||
ConstLit(ast::def_id), // the def ID of the constant
|
||||
@ -191,7 +191,7 @@ pub enum Lit {
|
||||
|
||||
// An option identifying a branch (either a literal, a enum variant or a
|
||||
// range)
|
||||
pub enum Opt {
|
||||
enum Opt {
|
||||
lit(Lit),
|
||||
var(/* disr val */ uint, @adt::Repr),
|
||||
range(@ast::expr, @ast::expr),
|
||||
@ -199,7 +199,7 @@ pub enum Opt {
|
||||
vec_len_ge(uint, /* slice */uint)
|
||||
}
|
||||
|
||||
pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
|
||||
fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
|
||||
match (a, b) {
|
||||
(&lit(a), &lit(b)) => {
|
||||
match (a, b) {
|
||||
@ -258,7 +258,7 @@ pub enum opt_result {
|
||||
lower_bound(Result),
|
||||
range_result(Result, Result),
|
||||
}
|
||||
pub fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result {
|
||||
fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result {
|
||||
let _icx = push_ctxt("match::trans_opt");
|
||||
let ccx = bcx.ccx();
|
||||
let bcx = bcx;
|
||||
@ -292,7 +292,7 @@ pub fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn variant_opt(bcx: @mut Block, pat_id: ast::NodeId)
|
||||
fn variant_opt(bcx: @mut Block, pat_id: ast::NodeId)
|
||||
-> Opt {
|
||||
let ccx = bcx.ccx();
|
||||
match ccx.tcx.def_map.get_copy(&pat_id) {
|
||||
@ -317,7 +317,7 @@ pub fn variant_opt(bcx: @mut Block, pat_id: ast::NodeId)
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum TransBindingMode {
|
||||
enum TransBindingMode {
|
||||
TrByValue(/*llbinding:*/ ValueRef),
|
||||
TrByRef,
|
||||
}
|
||||
@ -331,24 +331,24 @@ pub enum TransBindingMode {
|
||||
* - `id` is the node id of the binding
|
||||
* - `ty` is the Rust type of the binding */
|
||||
#[deriving(Clone)]
|
||||
pub struct BindingInfo {
|
||||
struct BindingInfo {
|
||||
llmatch: ValueRef,
|
||||
trmode: TransBindingMode,
|
||||
id: ast::NodeId,
|
||||
ty: ty::t,
|
||||
}
|
||||
|
||||
pub type BindingsMap = HashMap<ident, BindingInfo>;
|
||||
type BindingsMap = HashMap<ident, BindingInfo>;
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct ArmData<'self> {
|
||||
struct ArmData<'self> {
|
||||
bodycx: @mut Block,
|
||||
arm: &'self ast::arm,
|
||||
bindings_map: @BindingsMap
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct Match<'self> {
|
||||
struct Match<'self> {
|
||||
pats: ~[@ast::pat],
|
||||
data: ArmData<'self>
|
||||
}
|
||||
@ -364,7 +364,7 @@ impl<'self> Repr for Match<'self> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_nested_bindings(m: &[Match], col: uint) -> bool {
|
||||
fn has_nested_bindings(m: &[Match], col: uint) -> bool {
|
||||
for br in m.iter() {
|
||||
match br.pats[col].node {
|
||||
ast::pat_ident(_, _, Some(_)) => return true,
|
||||
@ -374,7 +374,7 @@ pub fn has_nested_bindings(m: &[Match], col: uint) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn expand_nested_bindings<'r>(bcx: @mut Block,
|
||||
fn expand_nested_bindings<'r>(bcx: @mut Block,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
val: ValueRef)
|
||||
@ -409,7 +409,7 @@ pub fn expand_nested_bindings<'r>(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assert_is_binding_or_wild(bcx: @mut Block, p: @ast::pat) {
|
||||
fn assert_is_binding_or_wild(bcx: @mut Block, p: @ast::pat) {
|
||||
if !pat_is_binding_or_wild(bcx.tcx().def_map, p) {
|
||||
bcx.sess().span_bug(
|
||||
p.span,
|
||||
@ -418,9 +418,9 @@ pub fn assert_is_binding_or_wild(bcx: @mut Block, p: @ast::pat) {
|
||||
}
|
||||
}
|
||||
|
||||
pub type enter_pat<'self> = &'self fn(@ast::pat) -> Option<~[@ast::pat]>;
|
||||
type enter_pat<'self> = &'self fn(@ast::pat) -> Option<~[@ast::pat]>;
|
||||
|
||||
pub fn enter_match<'r>(bcx: @mut Block,
|
||||
fn enter_match<'r>(bcx: @mut Block,
|
||||
dm: DefMap,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
@ -470,7 +470,7 @@ pub fn enter_match<'r>(bcx: @mut Block,
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn enter_default<'r>(bcx: @mut Block,
|
||||
fn enter_default<'r>(bcx: @mut Block,
|
||||
dm: DefMap,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
@ -485,7 +485,7 @@ pub fn enter_default<'r>(bcx: @mut Block,
|
||||
|
||||
do enter_match(bcx, dm, m, col, val) |p| {
|
||||
match p.node {
|
||||
ast::pat_wild | ast::pat_tup(_) | ast::pat_struct(*) => Some(~[]),
|
||||
ast::pat_wild | ast::pat_tup(_) => Some(~[]),
|
||||
ast::pat_ident(_, _, None) if pat_is_binding(dm, p) => Some(~[]),
|
||||
_ => None
|
||||
}
|
||||
@ -516,7 +516,7 @@ pub fn enter_default<'r>(bcx: @mut Block,
|
||||
// <nmatsakis> so all patterns must either be records (resp. tuples) or
|
||||
// wildcards
|
||||
|
||||
pub fn enter_opt<'r>(bcx: @mut Block,
|
||||
fn enter_opt<'r>(bcx: @mut Block,
|
||||
m: &[Match<'r>],
|
||||
opt: &Opt,
|
||||
col: uint,
|
||||
@ -628,7 +628,7 @@ pub fn enter_opt<'r>(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter_rec_or_struct<'r>(bcx: @mut Block,
|
||||
fn enter_rec_or_struct<'r>(bcx: @mut Block,
|
||||
dm: DefMap,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
@ -663,7 +663,7 @@ pub fn enter_rec_or_struct<'r>(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter_tup<'r>(bcx: @mut Block,
|
||||
fn enter_tup<'r>(bcx: @mut Block,
|
||||
dm: DefMap,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
@ -689,7 +689,7 @@ pub fn enter_tup<'r>(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter_tuple_struct<'r>(bcx: @mut Block,
|
||||
fn enter_tuple_struct<'r>(bcx: @mut Block,
|
||||
dm: DefMap,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
@ -715,7 +715,7 @@ pub fn enter_tuple_struct<'r>(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter_box<'r>(bcx: @mut Block,
|
||||
fn enter_box<'r>(bcx: @mut Block,
|
||||
dm: DefMap,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
@ -742,7 +742,7 @@ pub fn enter_box<'r>(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter_uniq<'r>(bcx: @mut Block,
|
||||
fn enter_uniq<'r>(bcx: @mut Block,
|
||||
dm: DefMap,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
@ -769,7 +769,7 @@ pub fn enter_uniq<'r>(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter_region<'r>(bcx: @mut Block,
|
||||
fn enter_region<'r>(bcx: @mut Block,
|
||||
dm: DefMap,
|
||||
m: &[Match<'r>],
|
||||
col: uint,
|
||||
@ -799,7 +799,7 @@ pub fn enter_region<'r>(bcx: @mut Block,
|
||||
// Returns the options in one column of matches. An option is something that
|
||||
// needs to be conditionally matched at runtime; for example, the discriminant
|
||||
// on a set of enum variants or a literal.
|
||||
pub fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] {
|
||||
fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] {
|
||||
let ccx = bcx.ccx();
|
||||
fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
|
||||
if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
|
||||
@ -865,12 +865,12 @@ pub fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] {
|
||||
return found;
|
||||
}
|
||||
|
||||
pub struct ExtractedBlock {
|
||||
struct ExtractedBlock {
|
||||
vals: ~[ValueRef],
|
||||
bcx: @mut Block
|
||||
}
|
||||
|
||||
pub fn extract_variant_args(bcx: @mut Block,
|
||||
fn extract_variant_args(bcx: @mut Block,
|
||||
repr: &adt::Repr,
|
||||
disr_val: uint,
|
||||
val: ValueRef)
|
||||
@ -893,7 +893,7 @@ fn match_datum(bcx: @mut Block, val: ValueRef, pat_id: ast::NodeId) -> Datum {
|
||||
}
|
||||
|
||||
|
||||
pub fn extract_vec_elems(bcx: @mut Block,
|
||||
fn extract_vec_elems(bcx: @mut Block,
|
||||
pat_span: span,
|
||||
pat_id: ast::NodeId,
|
||||
elem_count: uint,
|
||||
@ -947,24 +947,37 @@ pub fn extract_vec_elems(bcx: @mut Block,
|
||||
ExtractedBlock { vals: elems, bcx: bcx }
|
||||
}
|
||||
|
||||
// NB: This function does not collect fields from struct-like enum variants.
|
||||
pub fn collect_record_or_struct_fields(bcx: @mut Block,
|
||||
/// Checks every pattern in `m` at `col` column.
|
||||
/// If there are a struct pattern among them function
|
||||
/// returns list of all fields that are matched in these patterns.
|
||||
/// Function returns None if there is no struct pattern.
|
||||
/// Function doesn't collect fields from struct-like enum variants.
|
||||
/// Function can return empty list if there is only wildcard struct pattern.
|
||||
fn collect_record_or_struct_fields(bcx: @mut Block,
|
||||
m: &[Match],
|
||||
col: uint)
|
||||
-> ~[ast::ident] {
|
||||
-> Option<~[ast::ident]> {
|
||||
let mut fields: ~[ast::ident] = ~[];
|
||||
let mut found = false;
|
||||
for br in m.iter() {
|
||||
match br.pats[col].node {
|
||||
ast::pat_struct(_, ref fs, _) => {
|
||||
match ty::get(node_id_type(bcx, br.pats[col].id)).sty {
|
||||
ty::ty_struct(*) => extend(&mut fields, *fs),
|
||||
ty::ty_struct(*) => {
|
||||
extend(&mut fields, *fs);
|
||||
found = true;
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
if found {
|
||||
return Some(fields);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
||||
fn extend(idents: &mut ~[ast::ident], field_pats: &[ast::field_pat]) {
|
||||
for field_pat in field_pats.iter() {
|
||||
@ -976,7 +989,7 @@ pub fn collect_record_or_struct_fields(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pats_require_rooting(bcx: @mut Block,
|
||||
fn pats_require_rooting(bcx: @mut Block,
|
||||
m: &[Match],
|
||||
col: uint)
|
||||
-> bool {
|
||||
@ -987,7 +1000,7 @@ pub fn pats_require_rooting(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_pats_as_necessary(mut bcx: @mut Block,
|
||||
fn root_pats_as_necessary(mut bcx: @mut Block,
|
||||
m: &[Match],
|
||||
col: uint,
|
||||
val: ValueRef)
|
||||
@ -1018,23 +1031,23 @@ macro_rules! any_pat (
|
||||
)
|
||||
)
|
||||
|
||||
pub fn any_box_pat(m: &[Match], col: uint) -> bool {
|
||||
fn any_box_pat(m: &[Match], col: uint) -> bool {
|
||||
any_pat!(m, ast::pat_box(_))
|
||||
}
|
||||
|
||||
pub fn any_uniq_pat(m: &[Match], col: uint) -> bool {
|
||||
fn any_uniq_pat(m: &[Match], col: uint) -> bool {
|
||||
any_pat!(m, ast::pat_uniq(_))
|
||||
}
|
||||
|
||||
pub fn any_region_pat(m: &[Match], col: uint) -> bool {
|
||||
fn any_region_pat(m: &[Match], col: uint) -> bool {
|
||||
any_pat!(m, ast::pat_region(_))
|
||||
}
|
||||
|
||||
pub fn any_tup_pat(m: &[Match], col: uint) -> bool {
|
||||
fn any_tup_pat(m: &[Match], col: uint) -> bool {
|
||||
any_pat!(m, ast::pat_tup(_))
|
||||
}
|
||||
|
||||
pub fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
|
||||
fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
|
||||
do m.iter().any |br| {
|
||||
let pat = br.pats[col];
|
||||
match pat.node {
|
||||
@ -1050,9 +1063,9 @@ pub fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub type mk_fail = @fn() -> BasicBlockRef;
|
||||
type mk_fail = @fn() -> BasicBlockRef;
|
||||
|
||||
pub fn pick_col(m: &[Match]) -> uint {
|
||||
fn pick_col(m: &[Match]) -> uint {
|
||||
fn score(p: &ast::pat) -> uint {
|
||||
match p.node {
|
||||
ast::pat_lit(_) | ast::pat_enum(_, _) | ast::pat_range(_, _) => 1u,
|
||||
@ -1088,7 +1101,7 @@ pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
|
||||
// Compiles a comparison between two things.
|
||||
//
|
||||
// NB: This must produce an i1, not a Rust bool (i8).
|
||||
pub fn compare_values(cx: @mut Block,
|
||||
fn compare_values(cx: @mut Block,
|
||||
lhs: ValueRef,
|
||||
rhs: ValueRef,
|
||||
rhs_t: ty::t)
|
||||
@ -1204,7 +1217,7 @@ fn insert_lllocals(bcx: @mut Block,
|
||||
return bcx;
|
||||
}
|
||||
|
||||
pub fn compile_guard(bcx: @mut Block,
|
||||
fn compile_guard(bcx: @mut Block,
|
||||
guard_expr: @ast::expr,
|
||||
data: &ArmData,
|
||||
m: &[Match],
|
||||
@ -1261,7 +1274,7 @@ pub fn compile_guard(bcx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile_submatch(bcx: @mut Block,
|
||||
fn compile_submatch(bcx: @mut Block,
|
||||
m: &[Match],
|
||||
vals: &[ValueRef],
|
||||
chk: Option<mk_fail>) {
|
||||
@ -1336,22 +1349,24 @@ fn compile_submatch_continue(mut bcx: @mut Block,
|
||||
// required to root any values.
|
||||
assert!(any_box_pat(m, col) || !pats_require_rooting(bcx, m, col));
|
||||
|
||||
let rec_fields = collect_record_or_struct_fields(bcx, m, col);
|
||||
if rec_fields.len() > 0 {
|
||||
let pat_ty = node_id_type(bcx, pat_id);
|
||||
let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
|
||||
do expr::with_field_tys(tcx, pat_ty, None) |discr, field_tys| {
|
||||
let rec_vals = rec_fields.map(|field_name| {
|
||||
let ix = ty::field_idx_strict(tcx, *field_name, field_tys);
|
||||
adt::trans_field_ptr(bcx, pat_repr, val, discr, ix)
|
||||
});
|
||||
compile_submatch(
|
||||
bcx,
|
||||
enter_rec_or_struct(bcx, dm, m, col, rec_fields, val),
|
||||
vec::append(rec_vals, vals_left),
|
||||
chk);
|
||||
match collect_record_or_struct_fields(bcx, m, col) {
|
||||
Some(ref rec_fields) => {
|
||||
let pat_ty = node_id_type(bcx, pat_id);
|
||||
let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
|
||||
do expr::with_field_tys(tcx, pat_ty, None) |discr, field_tys| {
|
||||
let rec_vals = rec_fields.map(|field_name| {
|
||||
let ix = ty::field_idx_strict(tcx, *field_name, field_tys);
|
||||
adt::trans_field_ptr(bcx, pat_repr, val, discr, ix)
|
||||
});
|
||||
compile_submatch(
|
||||
bcx,
|
||||
enter_rec_or_struct(bcx, dm, m, col, *rec_fields, val),
|
||||
vec::append(rec_vals, vals_left),
|
||||
chk);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
None => {}
|
||||
}
|
||||
|
||||
if any_tup_pat(m, col) {
|
||||
@ -1670,7 +1685,7 @@ fn create_bindings_map(bcx: @mut Block, pat: @ast::pat) -> BindingsMap {
|
||||
return bindings_map;
|
||||
}
|
||||
|
||||
pub fn trans_match_inner(scope_cx: @mut Block,
|
||||
fn trans_match_inner(scope_cx: @mut Block,
|
||||
discr_expr: @ast::expr,
|
||||
arms: &[ast::arm],
|
||||
dest: Dest) -> @mut Block {
|
||||
@ -1752,7 +1767,7 @@ pub fn trans_match_inner(scope_cx: @mut Block,
|
||||
}
|
||||
}
|
||||
|
||||
pub enum IrrefutablePatternBindingMode {
|
||||
enum IrrefutablePatternBindingMode {
|
||||
// Stores the association between node ID and LLVM value in `lllocals`.
|
||||
BindLocal,
|
||||
// Stores the association between node ID and LLVM value in `llargs`.
|
||||
|
@ -8,8 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// xfail-test
|
||||
|
||||
enum Enum {
|
||||
Foo { foo: uint },
|
||||
Bar { bar: uint }
|
||||
|
24
src/test/run-pass/match-enum-struct-0.rs
Normal file
24
src/test/run-pass/match-enum-struct-0.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2013 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// regression test for issue #5625
|
||||
|
||||
enum E {
|
||||
Foo{f : int},
|
||||
Bar
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let e = Bar;
|
||||
match e {
|
||||
Foo{f: _f} => fail!(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
26
src/test/run-pass/match-enum-struct-1.rs
Normal file
26
src/test/run-pass/match-enum-struct-1.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2013 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
enum E {
|
||||
Foo{f : int},
|
||||
Bar
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let e = Foo{f: 1};
|
||||
match e {
|
||||
Foo{_} => (),
|
||||
_ => fail!(),
|
||||
}
|
||||
match e {
|
||||
Foo{f: _f} => (),
|
||||
_ => fail!(),
|
||||
}
|
||||
}
|
29
src/test/run-pass/match-struct-0.rs
Normal file
29
src/test/run-pass/match-struct-0.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2013 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct Foo{
|
||||
f : int,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let f = Foo{f: 1};
|
||||
match f {
|
||||
Foo{f: 0} => fail!(),
|
||||
Foo{_} => (),
|
||||
}
|
||||
match f {
|
||||
Foo{f: 0} => fail!(),
|
||||
Foo{f: _f} => (),
|
||||
}
|
||||
match f {
|
||||
Foo{f: 0} => fail!(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user