diff options
| author | Seo Sanghyeon <sanxiyn@gmail.com> | 2013-02-20 01:43:15 +0900 |
|---|---|---|
| committer | Seo Sanghyeon <sanxiyn@gmail.com> | 2013-02-20 02:44:02 +0900 |
| commit | a29023e9b2b42e94d77404496e72d0132aa44a6b (patch) | |
| tree | 82078f056e42128792c63b6dcdc89051d13e138e | |
| parent | 67ee95e943163d8d3dad439bfb0ce94e3e9c9aa4 (diff) | |
| download | rust-a29023e9b2b42e94d77404496e72d0132aa44a6b.tar.gz rust-a29023e9b2b42e94d77404496e72d0132aa44a6b.zip | |
Check type when struct is matched against enum-like pattern
Previously check always succeeded because struct type was derived from the matched expression, not the matched pattern.
| -rw-r--r-- | src/librustc/middle/ty.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/_match.rs | 13 | ||||
| -rw-r--r-- | src/test/compile-fail/match-struct.rs | 11 |
3 files changed, 23 insertions, 3 deletions
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c15010d7b7b..828db3b6a93 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2823,7 +2823,7 @@ pub pure fn ty_fn_ret(fty: t) -> t { } } -fn is_fn_ty(fty: t) -> bool { +pub fn is_fn_ty(fty: t) -> bool { match get(fty).sty { ty_bare_fn(_) => true, ty_closure(_) => true, diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index bd099923f2b..4cbefba31b1 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -92,7 +92,7 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, match structure_of(pcx.fcx, pat.span, expected) { ty::ty_enum(_, ref expected_substs) => { // Lookup the enum and variant def ids: - let v_def = lookup_def(pcx.fcx, path.span, pat.id); + let v_def = lookup_def(pcx.fcx, pat.span, pat.id); let v_def_ids = ast_util::variant_def_ids(v_def); // Assign the pattern the type of the *enum*, not the variant. @@ -125,8 +125,17 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, kind_name = "variant"; } ty::ty_struct(struct_def_id, ref expected_substs) => { + // Lookup the struct ctor def id + let s_def = lookup_def(pcx.fcx, pat.span, pat.id); + let s_def_id = ast_util::def_id_of_def(s_def); + // Assign the pattern the type of the struct. - let struct_tpt = ty::lookup_item_type(tcx, struct_def_id); + let ctor_tpt = ty::lookup_item_type(tcx, s_def_id); + let struct_tpt = if ty::is_fn_ty(ctor_tpt.ty) { + {ty: ty::ty_fn_ret(ctor_tpt.ty), ..ctor_tpt} + } else { + ctor_tpt + }; instantiate_path(pcx.fcx, path, struct_tpt, pat.span, pat.id, pcx.block_region); diff --git a/src/test/compile-fail/match-struct.rs b/src/test/compile-fail/match-struct.rs new file mode 100644 index 00000000000..fa406aa278e --- /dev/null +++ b/src/test/compile-fail/match-struct.rs @@ -0,0 +1,11 @@ +// error-pattern: mismatched types + +struct S { a: int } +enum E { C(int) } + +fn main() { + match S { a: 1 } { + C(_) => (), + _ => () + } +} |
