From b9896cbf6efa6736730f4666957b94b7e29d7fdf Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Sat, 20 Sep 2014 21:25:25 +0200 Subject: [PATCH] Fix handling of struct variants in a couple of places Fixes #17405. Fixes #17518. Fixes #17800. --- src/librustc/diagnostics.rs | 8 +++--- src/librustc/middle/typeck/check/_match.rs | 31 +++++++++++++++++----- src/librustc/middle/typeck/check/mod.rs | 2 +- src/test/compile-fail/issue-15896.rs | 2 +- src/test/compile-fail/issue-17405.rs | 19 +++++++++++++ src/test/compile-fail/issue-17518.rs | 17 ++++++++++++ src/test/compile-fail/issue-17800.rs | 21 +++++++++++++++ 7 files changed, 86 insertions(+), 14 deletions(-) create mode 100644 src/test/compile-fail/issue-17405.rs create mode 100644 src/test/compile-fail/issue-17518.rs create mode 100644 src/test/compile-fail/issue-17800.rs diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 0e85d7cc075..b39c4152168 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -38,7 +38,6 @@ E0017, E0019, E0020, - E0021, E0022, E0023, E0024, @@ -62,7 +61,6 @@ E0045, E0046, E0047, - E0048, E0049, E0050, E0051, @@ -117,8 +115,6 @@ E0109, E0110, E0113, - E0114, - E0115, E0116, E0117, E0118, @@ -152,5 +148,7 @@ E0158, E0159, E0161, - E0162 + E0162, + E0163, + E0164 ) diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index b5af2b26b29..18e2e6c4f09 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -382,26 +382,43 @@ pub fn check_struct_like_enum_variant_pat(pcx: &pat_ctxt, // Find the variant that was specified. match tcx.def_map.borrow().find(&pat_id) { - Some(&def::DefVariant(found_enum_id, variant_id, _)) + Some(&def::DefVariant(found_enum_id, variant_id, true)) if found_enum_id == enum_id => { // Get the struct fields from this struct-like enum variant. - let class_fields = ty::lookup_struct_fields(tcx, variant_id); - - check_struct_pat_fields(pcx, span, fields, class_fields, + let struct_fields = ty::lookup_struct_fields(tcx, variant_id); + check_struct_pat_fields(pcx, span, fields, struct_fields, variant_id, substitutions, etc); + fcx.write_ty(pat_id, expected); + } + Some(&def::DefVariant(_, _, false)) => { + let name = pprust::path_to_string(path); + span_err!(tcx.sess, span, E0163, + "`{}` does not name a struct variant", name); + fcx.write_error(pat_id); + } + Some(&def::DefVariant(_, _, true)) => { + let name = pprust::path_to_string(path); + span_err!(tcx.sess, span, E0164, + "`{}` does not name a variant of the type being matched against", name); + fcx.write_error(pat_id); } Some(&def::DefStruct(..)) | - Some(&def::DefVariant(..)) | Some(&def::DefTy(..)) => { let name = pprust::path_to_string(path); span_err!(tcx.sess, span, E0028, - "mismatched types: expected `{}`, found `{}`", - fcx.infcx().ty_to_string(expected), name); + "`{}` does not name a variant", name); + fcx.write_error(pat_id); } _ => { tcx.sess.span_bug(span, "resolve didn't write in variant"); } } + + if ty::type_is_error(fcx.node_ty(pat_id)) { + for field in fields.iter() { + check_pat(pcx, &*field.pat, ty::mk_err()); + } + } } // Pattern checking is top-down rather than bottom-up so that bindings get diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index bb490273e9f..75a412325be 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -4330,7 +4330,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt, // Resolve the path. let def = tcx.def_map.borrow().find(&id).map(|i| *i); let struct_id = match def { - Some(def::DefVariant(enum_id, variant_id, _)) => { + Some(def::DefVariant(enum_id, variant_id, true)) => { check_struct_enum_variant(fcx, id, expr.span, enum_id, variant_id, fields.as_slice()); enum_id diff --git a/src/test/compile-fail/issue-15896.rs b/src/test/compile-fail/issue-15896.rs index a873c1e3b3f..b7fa54e5c18 100644 --- a/src/test/compile-fail/issue-15896.rs +++ b/src/test/compile-fail/issue-15896.rs @@ -18,7 +18,7 @@ enum E { B(R, Tau) } let e = B(REB(()), Tau { t: 3 }); let u = match e { B( - Tau{t: x}, //~ ERROR mismatched types + Tau{t: x}, //~ ERROR `Tau` does not name a variant _) => x, }; } diff --git a/src/test/compile-fail/issue-17405.rs b/src/test/compile-fail/issue-17405.rs new file mode 100644 index 00000000000..b80cfb521ef --- /dev/null +++ b/src/test/compile-fail/issue-17405.rs @@ -0,0 +1,19 @@ +// Copyright 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. + +enum Foo { + Bar(int) +} + +fn main() { + match Bar(1i) { + Foo { i } => () //~ ERROR `Foo` does not name a variant + } +} diff --git a/src/test/compile-fail/issue-17518.rs b/src/test/compile-fail/issue-17518.rs new file mode 100644 index 00000000000..0410fadeb78 --- /dev/null +++ b/src/test/compile-fail/issue-17518.rs @@ -0,0 +1,17 @@ +// Copyright 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. + +enum SomeEnum { + E +} + +fn main() { + E { name: "foobar" }; //~ ERROR `E` does not name a structure +} diff --git a/src/test/compile-fail/issue-17800.rs b/src/test/compile-fail/issue-17800.rs new file mode 100644 index 00000000000..8ef016e3fd5 --- /dev/null +++ b/src/test/compile-fail/issue-17800.rs @@ -0,0 +1,21 @@ +// Copyright 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. + +enum MyOption { + MySome(T), + MyNone, +} + +fn main() { + match MySome(42i) { + MySome { x: 42i } => (), //~ ERROR `MySome` does not name a struct variant + _ => (), + } +}