Skip to content

Fix various bugs around empty structs and patterns #29383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 28, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/librustc/middle/intrinsicck.rs
Original file line number Diff line number Diff line change
@@ -225,11 +225,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
intravisit::walk_fn(self, fk, fd, b, s);
self.param_envs.pop();
}
FnKind::Closure(..) => {
FnKind::Closure => {
intravisit::walk_fn(self, fk, fd, b, s);
}
}

}

fn visit_expr(&mut self, expr: &hir::Expr) {
2 changes: 1 addition & 1 deletion src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
@@ -1424,7 +1424,7 @@ impl<'tcx> cmt_<'tcx> {
NonAliasable
}

Categorization::StaticItem(..) => {
Categorization::StaticItem => {
if self.mutbl.is_mutable() {
FreelyAliasable(AliasableStaticMut)
} else {
4 changes: 2 additions & 2 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
@@ -184,7 +184,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
this.walk_fn(fk, fd, b, s)
})
}
FnKind::Closure(..) => {
FnKind::Closure => {
self.walk_fn(fk, fd, b, s)
}
}
@@ -479,7 +479,7 @@ impl<'a> LifetimeContext<'a> {
self.visit_generics(&sig.generics);
self.visit_explicit_self(&sig.explicit_self);
}
FnKind::Closure(..) => {
FnKind::Closure => {
intravisit::walk_fn_decl(self, fd);
}
}
2 changes: 1 addition & 1 deletion src/librustc/middle/traits/coherence.rs
Original file line number Diff line number Diff line change
@@ -301,7 +301,7 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
ty::TyInt(..) |
ty::TyUint(..) |
ty::TyFloat(..) |
ty::TyStr(..) |
ty::TyStr |
ty::TyBareFn(..) |
ty::TyArray(..) |
ty::TySlice(..) |
10 changes: 5 additions & 5 deletions src/librustc/middle/traits/select.rs
Original file line number Diff line number Diff line change
@@ -1563,7 +1563,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}

match other {
&ObjectCandidate(..) |
&ObjectCandidate |
&ParamCandidate(_) | &ProjectionCandidate => match victim {
&DefaultImplCandidate(..) => {
self.tcx().sess.bug(
@@ -1572,16 +1572,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
&ImplCandidate(..) |
&ClosureCandidate(..) |
&FnPointerCandidate(..) |
&BuiltinObjectCandidate(..) |
&BuiltinUnsizeCandidate(..) |
&FnPointerCandidate |
&BuiltinObjectCandidate |
&BuiltinUnsizeCandidate |
&DefaultImplObjectCandidate(..) |
&BuiltinCandidate(..) => {
// We have a where-clause so don't go around looking
// for impls.
true
}
&ObjectCandidate(..) |
&ObjectCandidate |
&ProjectionCandidate => {
// Arbitrarily give param candidates priority
// over projection and object candidates.
8 changes: 4 additions & 4 deletions src/librustc/middle/ty/outlives.rs
Original file line number Diff line number Diff line change
@@ -188,21 +188,21 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
// the type and then visits the types that are lexically
// contained within. (The comments refer to relevant rules
// from RFC1214.)
ty::TyBool(..) | // OutlivesScalar
ty::TyChar(..) | // OutlivesScalar
ty::TyBool | // OutlivesScalar
ty::TyChar | // OutlivesScalar
ty::TyInt(..) | // OutlivesScalar
ty::TyUint(..) | // OutlivesScalar
ty::TyFloat(..) | // OutlivesScalar
ty::TyEnum(..) | // OutlivesNominalType
ty::TyStruct(..) | // OutlivesNominalType
ty::TyBox(..) | // OutlivesNominalType (ish)
ty::TyStr(..) | // OutlivesScalar (ish)
ty::TyStr | // OutlivesScalar (ish)
ty::TyArray(..) | // ...
ty::TySlice(..) | // ...
ty::TyRawPtr(..) | // ...
ty::TyRef(..) | // OutlivesReference
ty::TyTuple(..) | // ...
ty::TyError(..) => {
ty::TyError => {
push_region_constraints(out, ty.regions());
for subty in ty.walk_shallow() {
compute_components(infcx, subty, out);
16 changes: 8 additions & 8 deletions src/librustc_borrowck/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
@@ -540,14 +540,14 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
ol, old_loan_msg)
}

euv::OverloadedOperator(..) |
euv::AddrOf(..) |
euv::AutoRef(..) |
euv::AutoUnsafe(..) |
euv::ClosureInvocation(..) |
euv::ForLoop(..) |
euv::RefBinding(..) |
euv::MatchDiscriminant(..) => {
euv::OverloadedOperator |
euv::AddrOf |
euv::AutoRef |
euv::AutoUnsafe |
euv::ClosureInvocation |
euv::ForLoop |
euv::RefBinding |
euv::MatchDiscriminant => {
format!("previous borrow of `{}` occurs here{}",
ol, old_loan_msg)
}
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
self.extend(result, &cmt, LpInterior(i.cleaned()))
}

Categorization::StaticItem(..) => {
Categorization::StaticItem => {
Safe
}

6 changes: 3 additions & 3 deletions src/librustc_borrowck/borrowck/mod.rs
Original file line number Diff line number Diff line change
@@ -942,8 +942,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
"consider changing this closure to take self by mutable reference");
}
}
mc::AliasableStatic(..) |
mc::AliasableStaticMut(..) => {
mc::AliasableStatic |
mc::AliasableStaticMut => {
span_err!(
self.tcx.sess, span, E0388,
"{} in a static location", prefix);
@@ -998,7 +998,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
pub fn note_and_explain_bckerr(&self, err: BckError<'tcx>) {
let code = err.code;
match code {
err_mutbl(..) => {
err_mutbl => {
match err.cmt.note {
mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => {
// If this is an `Fn` closure, it simply can't mutate upvars.
2 changes: 1 addition & 1 deletion src/librustc_mir/build/matches/simplify.rs
Original file line number Diff line number Diff line change
@@ -66,7 +66,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
candidate: &mut Candidate<'pat, 'tcx>)
-> Result<BasicBlock, MatchPair<'pat, 'tcx>> {
match *match_pair.pattern.kind {
PatternKind::Wild(..) => {
PatternKind::Wild => {
// nothing left to do
Ok(block)
}
2 changes: 1 addition & 1 deletion src/librustc_mir/hair/cx/expr.rs
Original file line number Diff line number Diff line change
@@ -178,7 +178,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
}
ty::TyEnum(adt, substs) => {
match cx.tcx.def_map.borrow()[&self.id].full_def() {
def::DefVariant(enum_id, variant_id, true) => {
def::DefVariant(enum_id, variant_id, _) => {
debug_assert!(adt.did == enum_id);
let index = adt.variant_index_with_id(variant_id);
let field_refs = field_refs(&adt.variants[index], fields);
2 changes: 1 addition & 1 deletion src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
@@ -625,7 +625,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
self.visit_explicit_self(&sig.explicit_self);
MethodRibKind
}
FnKind::Closure(..) => ClosureRibKind(node_id),
FnKind::Closure => ClosureRibKind(node_id),
};
self.resolve_function(rib_kind, declaration, block);
}
4 changes: 2 additions & 2 deletions src/librustc_trans/trans/type_of.rs
Original file line number Diff line number Diff line change
@@ -247,7 +247,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
}
}

ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError(..) => {
ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError => {
cx.sess().bug(&format!("fictitious type {:?} in sizing_type_of()",
t))
}
@@ -451,7 +451,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
ty::TyInfer(..) => cx.sess().bug("type_of with TyInfer"),
ty::TyProjection(..) => cx.sess().bug("type_of with TyProjection"),
ty::TyParam(..) => cx.sess().bug("type_of with ty_param"),
ty::TyError(..) => cx.sess().bug("type_of with TyError"),
ty::TyError => cx.sess().bug("type_of with TyError"),
};

debug!("--> mapped t={:?} to llty={}",
84 changes: 61 additions & 23 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ use check::{check_expr_with_lvalue_pref};
use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
use require_same_types;
use util::nodemap::FnvHashMap;
use session::Session;

use std::cmp;
use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -136,6 +137,12 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
}
hir::PatEnum(..) | hir::PatIdent(..)
if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
if let hir::PatEnum(ref path, ref subpats) = pat.node {
if !(subpats.is_some() && subpats.as_ref().unwrap().is_empty()) {
bad_struct_kind_err(tcx.sess, pat.span, path, false);
return;
}
}
let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
let const_scheme = tcx.lookup_item_type(const_did);
assert!(const_scheme.generics.is_empty());
@@ -192,11 +199,12 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
}
hir::PatIdent(_, ref path, _) => {
let path = hir_util::ident_to_path(path.span, path.node);
check_pat_enum(pcx, pat, &path, Some(&[]), expected);
check_pat_enum(pcx, pat, &path, Some(&[]), expected, false);
}
hir::PatEnum(ref path, ref subpats) => {
let subpats = subpats.as_ref().map(|v| &v[..]);
check_pat_enum(pcx, pat, path, subpats, expected);
let is_tuple_struct_pat = !(subpats.is_some() && subpats.unwrap().is_empty());
check_pat_enum(pcx, pat, path, subpats, expected, is_tuple_struct_pat);
}
hir::PatQPath(ref qself, ref path) => {
let self_ty = fcx.to_ty(&qself.ty);
@@ -572,11 +580,19 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
fcx.write_substs(pat.id, ty::ItemSubsts { substs: item_substs.clone() });
}

// This function exists due to the warning "diagnostic code E0164 already used"
fn bad_struct_kind_err(sess: &Session, span: Span, path: &hir::Path, is_warning: bool) {
let name = pprust::path_to_string(path);
span_err_or_warn!(is_warning, sess, span, E0164,
"`{}` does not name a tuple variant or a tuple struct", name);
}

pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
pat: &hir::Pat,
path: &hir::Path,
subpats: Option<&'tcx [P<hir::Pat>]>,
expected: Ty<'tcx>)
expected: Ty<'tcx>,
is_tuple_struct_pat: bool)
{
// Typecheck the path.
let fcx = pcx.fcx;
@@ -618,25 +634,52 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
path_scheme, &ctor_predicates,
opt_ty, def, pat.span, pat.id);

let report_bad_struct_kind = |is_warning| {
bad_struct_kind_err(tcx.sess, pat.span, path, is_warning);
fcx.write_error(pat.id);

if let Some(subpats) = subpats {
for pat in subpats {
check_pat(pcx, &**pat, tcx.types.err);
}
}
};

// If we didn't have a fully resolved path to start with, we had an
// associated const, and we should quit now, since the rest of this
// function uses checks specific to structs and enums.
if path_res.depth != 0 {
let pat_ty = fcx.node_ty(pat.id);
demand::suptype(fcx, pat.span, expected, pat_ty);
if is_tuple_struct_pat {
report_bad_struct_kind(false);
} else {
let pat_ty = fcx.node_ty(pat.id);
demand::suptype(fcx, pat.span, expected, pat_ty);
}
return;
}

let pat_ty = fcx.node_ty(pat.id);
demand::eqtype(fcx, pat.span, expected, pat_ty);


let real_path_ty = fcx.node_ty(pat.id);
let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
ty::TyEnum(enum_def, expected_substs)
if def == def::DefVariant(enum_def.did, def.def_id(), false) =>
{
let variant = enum_def.variant_of_def(def);
if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
// Matching unit variants with tuple variant patterns (`UnitVariant(..)`)
// is allowed for backward compatibility.
let is_special_case = variant.kind() == ty::VariantKind::Unit;
report_bad_struct_kind(is_special_case);
if !is_special_case {
return
} else {
span_note!(tcx.sess, pat.span,
"this warning will become a HARD ERROR in a future release. \
See RFC 218 for details.");
}
}
(variant.fields
.iter()
.map(|f| fcx.instantiate_type_scheme(pat.span,
@@ -646,26 +689,21 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
"variant")
}
ty::TyStruct(struct_def, expected_substs) => {
(struct_def.struct_variant()
.fields
.iter()
.map(|f| fcx.instantiate_type_scheme(pat.span,
expected_substs,
&f.unsubst_ty()))
.collect(),
let variant = struct_def.struct_variant();
if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
report_bad_struct_kind(false);
return;
}
(variant.fields
.iter()
.map(|f| fcx.instantiate_type_scheme(pat.span,
expected_substs,
&f.unsubst_ty()))
.collect(),
"struct")
}
_ => {
let name = pprust::path_to_string(path);
span_err!(tcx.sess, pat.span, E0164,
"`{}` does not name a non-struct variant or a tuple struct", name);
fcx.write_error(pat.id);

if let Some(subpats) = subpats {
for pat in subpats {
check_pat(pcx, &**pat, tcx.types.err);
}
}
report_bad_struct_kind(false);
return;
}
};
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
@@ -1052,7 +1052,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
(impl_def_id, substs, ref_obligations)
}

ObjectCandidate(..) |
ObjectCandidate |
TraitCandidate |
WhereClauseCandidate(..) => {
// These have no additional conditions to check.
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -1446,7 +1446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
{
let (adt, variant) = match def {
def::DefVariant(enum_id, variant_id, true) => {
def::DefVariant(enum_id, variant_id, _) => {
let adt = self.tcx().lookup_adt_def(enum_id);
(adt, adt.variant_with_id(variant_id))
}
2 changes: 1 addition & 1 deletion src/librustc_typeck/coherence/mod.rs
Original file line number Diff line number Diff line change
@@ -69,7 +69,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
}

TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
TyStr(..) | TyArray(..) | TySlice(..) | TyBareFn(..) | TyTuple(..) |
TyStr | TyArray(..) | TySlice(..) | TyBareFn(..) | TyTuple(..) |
TyParam(..) | TyError |
TyRawPtr(_) | TyRef(_, _) | TyProjection(..) => {
None
4 changes: 2 additions & 2 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -776,7 +776,7 @@ impl Clean<Option<Lifetime>> for ty::Region {
ty::ReScope(..) |
ty::ReVar(..) |
ty::ReSkolemized(..) |
ty::ReEmpty(..) => None
ty::ReEmpty => None
}
}
}
@@ -1609,7 +1609,7 @@ impl Clean<Type> for hir::Ty {
TyPolyTraitRef(ref bounds) => {
PolyTraitRef(bounds.clean(cx))
},
TyInfer(..) => {
TyInfer => {
Infer
},
TyTypeof(..) => {
17 changes: 7 additions & 10 deletions src/test/compile-fail/empty-struct-braces-gate-2.rs
Original file line number Diff line number Diff line change
@@ -20,8 +20,7 @@ enum E {
fn main() {
let e2: Empty2 = Empty2 {}; //~ ERROR empty structs and enum variants with braces are unstable
let e2: Empty2 = Empty2;
// Issue #28692
// let e5: E = E::Empty5 {}; // ERROR empty structs and enum variants with braces are unstable
let e5: E = E::Empty5 {}; //~ ERROR empty structs and enum variants with braces are unstable
let e5: E = E::Empty5;

match e2 {
@@ -33,17 +32,15 @@ fn main() {
match e2 {
Empty2 { .. } => {} //~ ERROR empty structs and enum variants with braces are unstable
}
// Issue #28692
// match e5 {
// E::Empty5 {} => {} // ERROR empty structs and enum variants with braces are unstable
// }
match e5 {
E::Empty5 {} => {} //~ ERROR empty structs and enum variants with braces are unstable
}
match e5 {
E::Empty5 => {}
}
// Issue #28692
// match e5 {
// E::Empty5 { .. } => {} // ERROR empty structs and enum variants with braces are unstable
// }
match e5 {
E::Empty5 { .. } => {} //~ ERROR empty structs and enum variants with braces are unstable
}

let e22 = Empty2 { ..e2 }; //~ ERROR empty structs and enum variants with braces are unstable
}
10 changes: 4 additions & 6 deletions src/test/compile-fail/empty-struct-braces-pat-1.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@

// Can't use empty braced struct as constant pattern

#![deny(warnings)]
#![feature(braced_empty_structs)]

struct Empty1 {}
@@ -23,11 +22,10 @@ fn main() {
let e1 = Empty1 {};
let e2 = E::Empty2 {};

// Issue #28692
// match e1 {
// Empty1 => () // ERROR incorrect error
// }
match e1 {
Empty1 => () // Not an error, `Empty1` is interpreted as a new binding
}
match e2 {
E::Empty2 => () //~ ERROR `E::Empty2` does not name a non-struct variant or a tuple struct
E::Empty2 => () //~ ERROR `E::Empty2` does not name a tuple variant or a tuple struct
}
}
12 changes: 0 additions & 12 deletions src/test/compile-fail/empty-struct-braces-pat-2.rs
Original file line number Diff line number Diff line change
@@ -14,13 +14,8 @@

struct Empty1 {}

enum E {
Empty2 {}
}

fn main() {
let e1 = Empty1 {};
let e2 = E::Empty2 {};

// Rejected by parser as yet
// match e1 {
@@ -29,11 +24,4 @@ fn main() {
match e1 {
Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1`
}
// Issue #28692
// match e2 {
// E::Empty2() => () // ERROR unresolved enum variant, struct or const `Empty2`
// }
// match e2 {
// E::Empty2(..) => () // ERROR unresolved enum variant, struct or const `Empty2`
// }
}
29 changes: 29 additions & 0 deletions src/test/compile-fail/empty-struct-braces-pat-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2015 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.

// Can't use empty braced struct as enum pattern

#![feature(braced_empty_structs)]

enum E {
Empty2 {}
}

fn main() {
let e2 = E::Empty2 {};

// Rejected by parser as yet
// match e2 {
// E::Empty2() => () // ERROR `E::Empty2` does not name a tuple variant or a tuple struct
// }
match e2 {
E::Empty2(..) => () //~ ERROR `E::Empty2` does not name a tuple variant or a tuple struct
}
}
21 changes: 10 additions & 11 deletions src/test/compile-fail/empty-struct-unit-pat.rs
Original file line number Diff line number Diff line change
@@ -12,8 +12,6 @@

#![feature(braced_empty_structs)]

FIXME //~ ERROR expected item, found `FIXME`

struct Empty1;

enum E {
@@ -24,17 +22,18 @@ fn main() {
let e1 = Empty1;
let e2 = E::Empty2;

// Issue #28692
// match e1 {
// Empty1() => () // ERROR variable `Empty1` should have a snake case name
// }
// Rejected by parser as yet
// match e1 {
// Empty1(..) => () // ERROR variable `Empty1` should have a snake case name
// }
// match e2 {
// E::Empty2() => () // ERROR variable `Empty2` should have a snake case name
// Empty1() => () // ERROR `Empty1` does not name a tuple variant or a tuple struct
// }
match e1 {
Empty1(..) => () //~ ERROR `Empty1` does not name a tuple variant or a tuple struct
}
// Rejected by parser as yet
// match e2 {
// E::Empty2(..) => () // ERROR variable `Empty2` should have a snake case name
// E::Empty2() => () // ERROR `E::Empty2` does not name a tuple variant or a tuple struct
// }
match e2 {
E::Empty2(..) => () //~ WARN `E::Empty2` does not name a tuple variant or a tuple struct
}
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-19086.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,6 @@ fn main() {
let f = FooB { x: 3, y: 4 };
match f {
FooB(a, b) => println!("{} {}", a, b),
//~^ ERROR `FooB` does not name a non-struct variant or a tuple struct
//~^ ERROR `FooB` does not name a tuple variant or a tuple struct
}
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-27831.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ fn main() {
let Bar { .. } = x; //~ ERROR empty structs and enum variants with braces are unstable

match Enum::Bar {
Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct
Enum::Bar { .. } //~ ERROR empty structs and enum variants with braces are unstable
=> {}
Enum::Foo { .. } //~ ERROR `Enum::Foo` does not name a struct
=> {}
26 changes: 26 additions & 0 deletions src/test/compile-fail/issue-28992-empty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2015 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.

// Can't use constants as tuple struct patterns

#![feature(associated_consts)]

const C1: i32 = 0;

struct S;

impl S {
const C2: i32 = 0;
}

fn main() {
if let C1(..) = 0 {} //~ ERROR `C1` does not name a tuple variant or a tuple struct
if let S::C2(..) = 0 {} //~ ERROR `S::C2` does not name a tuple variant or a tuple struct
}
1 change: 1 addition & 0 deletions src/test/compile-fail/match-pattern-field-mismatch-2.rs
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ fn main() {
color::cmyk(_, _, _, _) => { }
color::no_color(_) => { }
//~^ ERROR this pattern has 1 field, but the corresponding variant has no fields
//~^^ WARN `color::no_color` does not name a tuple variant or a tuple struct
}
}
}
8 changes: 4 additions & 4 deletions src/test/compile-fail/move-fragments-2.rs
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ pub fn test_match_partial(p: Lonely<D, D>) {
//~^ ERROR parent_of_fragments: `$(local p)`
//~| ERROR assigned_leaf_path: `($(local p) as Lonely::Zero)`
match p {
Zero(..) => {}
Zero => {}
_ => {}
}
}
@@ -44,7 +44,7 @@ pub fn test_match_full(p: Lonely<D, D>) {
//~| ERROR assigned_leaf_path: `($(local p) as Lonely::One)`
//~| ERROR assigned_leaf_path: `($(local p) as Lonely::Two)`
match p {
Zero(..) => {}
Zero => {}
One(..) => {}
Two(..) => {}
}
@@ -59,7 +59,7 @@ pub fn test_match_bind_one(p: Lonely<D, D>) {
//~| ERROR assigned_leaf_path: `($(local p) as Lonely::Two)`
//~| ERROR assigned_leaf_path: `$(local data)`
match p {
Zero(..) => {}
Zero => {}
One(data) => {}
Two(..) => {}
}
@@ -78,7 +78,7 @@ pub fn test_match_bind_many(p: Lonely<D, D>) {
//~| ERROR assigned_leaf_path: `$(local left)`
//~| ERROR assigned_leaf_path: `$(local right)`
match p {
Zero(..) => {}
Zero => {}
One(data) => {}
Two(left, right) => {}
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/move-fragments-3.rs
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ pub fn test_match_bind_and_underscore(p: Lonely<D, D>) {
//~| ERROR assigned_leaf_path: `$(local left)`

match p {
Zero(..) => {}
Zero => {}

One(_) => {} // <-- does not fragment `($(local p) as One)` ...

1 change: 1 addition & 0 deletions src/test/compile-fail/pattern-error-continue.rs
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@ fn main() {
match A::B(1, 2) {
A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but
A::D(_) => (), //~ ERROR this pattern has 1 field, but
//~^ WARN `A::D` does not name a tuple variant or a tuple struct
_ => ()
}
match 'c' {
20 changes: 9 additions & 11 deletions src/test/run-pass/empty-struct-braces.rs
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ fn main() {
let e3: Empty3 = Empty3 {};
let e3: Empty3 = Empty3;
let e4: E = E::Empty4 {};
// let e5: E = E::Empty5 {}; // Issue #28692
let e5: E = E::Empty5 {};
let e5: E = E::Empty5;

match e1 {
@@ -46,11 +46,10 @@ fn main() {
E::Empty4 {} => {}
_ => {}
}
// Issue #28692
// match e5 {
// E::Empty5 {} => {}
// _ => {}
// }
match e5 {
E::Empty5 {} => {}
_ => {}
}

match e1 {
Empty1 { .. } => {}
@@ -65,11 +64,10 @@ fn main() {
E::Empty4 { .. } => {}
_ => {}
}
// Issue #28692
// match e5 {
// E::Empty5 { .. } => {}
// _ => {}
// }
match e5 {
E::Empty5 { .. } => {}
_ => {}
}

match e2 {
Empty2 => {}
9 changes: 0 additions & 9 deletions src/test/run-pass/issue-14308.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@


struct A(isize);
struct B;

fn main() {
let x = match A(3) {
@@ -22,12 +21,4 @@ fn main() {
A(..) => 2
};
assert_eq!(x, 2);

// This next test uses a (..) wildcard match on a nullary struct.
// There's no particularly good reason to support this, but it's currently allowed,
// and this makes sure it doesn't ICE or break LLVM.
let x = match B {
B(..) => 3
};
assert_eq!(x, 3);
}
2 changes: 1 addition & 1 deletion src/test/run-pass/issue-1701.rs
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ fn noise(a: animal) -> Option<String> {
animal::cat(..) => { Some("meow".to_string()) }
animal::dog(..) => { Some("woof".to_string()) }
animal::rabbit(..) => { None }
animal::tiger(..) => { Some("roar".to_string()) }
animal::tiger => { Some("roar".to_string()) }
}
}