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(..) => {
Loading