Skip to content

Commit 37849a0

Browse files
committed
Auto merge of #42969 - arielb1:struct-err, r=eddyb
mem_categorization: handle type-based paths in variant patterns These can't be used in correct programs, but must be handled in order to prevent ICEs. Fixes #42880. r? @eddyb
2 parents e72580c + 1ea6813 commit 37849a0

File tree

3 files changed

+64
-55
lines changed

3 files changed

+64
-55
lines changed

src/librustc/middle/expr_use_visitor.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
816816
fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
817817
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
818818

819-
let tcx = self.tcx();
820819
let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
821820
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| {
822821
if let PatKind::Binding(bmode, def_id, ..) = pat.node {
@@ -864,13 +863,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
864863
match def {
865864
Def::Variant(variant_did) |
866865
Def::VariantCtor(variant_did, ..) => {
867-
let enum_did = tcx.parent_def_id(variant_did).unwrap();
868-
let downcast_cmt = if tcx.adt_def(enum_did).is_univariant() {
869-
cmt_pat
870-
} else {
871-
let cmt_pat_ty = cmt_pat.ty;
872-
mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
873-
};
866+
let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
874867

875868
debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
876869
delegate.matched_pat(pat, downcast_cmt, match_mode);

src/librustc/middle/mem_categorization.rs

+45-47
Original file line numberDiff line numberDiff line change
@@ -1032,22 +1032,29 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
10321032
ret
10331033
}
10341034

1035-
pub fn cat_downcast<N:ast_node>(&self,
1036-
node: &N,
1037-
base_cmt: cmt<'tcx>,
1038-
downcast_ty: Ty<'tcx>,
1039-
variant_did: DefId)
1040-
-> cmt<'tcx> {
1041-
let ret = Rc::new(cmt_ {
1042-
id: node.id(),
1043-
span: node.span(),
1044-
mutbl: base_cmt.mutbl.inherit(),
1045-
cat: Categorization::Downcast(base_cmt, variant_did),
1046-
ty: downcast_ty,
1047-
note: NoteNone
1048-
});
1049-
debug!("cat_downcast ret={:?}", ret);
1050-
ret
1035+
pub fn cat_downcast_if_needed<N:ast_node>(&self,
1036+
node: &N,
1037+
base_cmt: cmt<'tcx>,
1038+
variant_did: DefId)
1039+
-> cmt<'tcx> {
1040+
// univariant enums do not need downcasts
1041+
let base_did = self.tcx.parent_def_id(variant_did).unwrap();
1042+
if !self.tcx.adt_def(base_did).is_univariant() {
1043+
let base_ty = base_cmt.ty;
1044+
let ret = Rc::new(cmt_ {
1045+
id: node.id(),
1046+
span: node.span(),
1047+
mutbl: base_cmt.mutbl.inherit(),
1048+
cat: Categorization::Downcast(base_cmt, variant_did),
1049+
ty: base_ty,
1050+
note: NoteNone
1051+
});
1052+
debug!("cat_downcast ret={:?}", ret);
1053+
ret
1054+
} else {
1055+
debug!("cat_downcast univariant={:?}", base_cmt);
1056+
base_cmt
1057+
}
10511058
}
10521059

10531060
pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()>
@@ -1109,45 +1116,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
11091116

11101117
op(cmt.clone(), pat);
11111118

1112-
// Note: This goes up here (rather than within the PatKind::TupleStruct arm
1113-
// alone) because PatKind::Struct can also refer to variants.
1114-
let cmt = match pat.node {
1115-
PatKind::Path(hir::QPath::Resolved(_, ref path)) |
1116-
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
1117-
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
1118-
match path.def {
1119-
Def::Err => {
1120-
debug!("access to unresolvable pattern {:?}", pat);
1121-
return Err(())
1122-
}
1123-
Def::Variant(variant_did) |
1124-
Def::VariantCtor(variant_did, ..) => {
1125-
// univariant enums do not need downcasts
1126-
let enum_did = self.tcx.parent_def_id(variant_did).unwrap();
1127-
if !self.tcx.adt_def(enum_did).is_univariant() {
1128-
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
1129-
} else {
1130-
cmt
1131-
}
1132-
}
1133-
_ => cmt
1134-
}
1135-
}
1136-
_ => cmt
1137-
};
1138-
11391119
match pat.node {
11401120
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
11411121
let def = self.tables.qpath_def(qpath, pat.id);
1142-
let expected_len = match def {
1122+
let (cmt, expected_len) = match def {
1123+
Def::Err => {
1124+
debug!("access to unresolvable pattern {:?}", pat);
1125+
return Err(())
1126+
}
11431127
Def::VariantCtor(def_id, CtorKind::Fn) => {
11441128
let enum_def = self.tcx.parent_def_id(def_id).unwrap();
1145-
self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()
1129+
(self.cat_downcast_if_needed(pat, cmt, def_id),
1130+
self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
11461131
}
11471132
Def::StructCtor(_, CtorKind::Fn) => {
11481133
match self.pat_ty(&pat)?.sty {
11491134
ty::TyAdt(adt_def, _) => {
1150-
adt_def.struct_variant().fields.len()
1135+
(cmt, adt_def.struct_variant().fields.len())
11511136
}
11521137
ref ty => {
11531138
span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
@@ -1168,8 +1153,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
11681153
}
11691154
}
11701155

1171-
PatKind::Struct(_, ref field_pats, _) => {
1156+
PatKind::Struct(ref qpath, ref field_pats, _) => {
11721157
// {f1: p1, ..., fN: pN}
1158+
let def = self.tables.qpath_def(qpath, pat.id);
1159+
let cmt = match def {
1160+
Def::Err => {
1161+
debug!("access to unresolvable pattern {:?}", pat);
1162+
return Err(())
1163+
},
1164+
Def::Variant(variant_did) |
1165+
Def::VariantCtor(variant_did, ..) => {
1166+
self.cat_downcast_if_needed(pat, cmt, variant_did)
1167+
},
1168+
_ => cmt
1169+
};
1170+
11731171
for fp in field_pats {
11741172
let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2)
11751173
let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty);

src/test/compile-fail/issue-42880.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
type Value = String;
12+
13+
fn main() {
14+
let f = |&Value::String(_)| (); //~ ERROR no associated item named
15+
16+
let vec: Vec<Value> = Vec::new();
17+
vec.last().map(f);
18+
}

0 commit comments

Comments
 (0)