Skip to content

Commit 94402f2

Browse files
committed
Distinguish move semantics for a @ Var(_) from that of Var(_).
Note that due to PR rust-lang#16053, we only actually deal with `a @ Var(_)` here, (as opposed to a hypothetical `a @ Var(ref b)`, which cannot currenty arise, and maybe will never be supported for non-copy data).
1 parent 21dd404 commit 94402f2

File tree

2 files changed

+67
-7
lines changed

2 files changed

+67
-7
lines changed

src/librustc/middle/expr_use_visitor.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,37 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
10001000
debug!("walk_pat binding consuming pat");
10011001
delegate.consume_pat(pat, cmt_pat, mode);
10021002
}
1003+
1004+
ast::PatWild(_) => {
1005+
match match_mode {
1006+
NonBindingMatch |
1007+
BorrowingMatch |
1008+
CopyingMatch => {}
1009+
1010+
MovingMatch => {
1011+
// On `enum E { Variant(Box<T>) }`, both of
1012+
// the match arms:
1013+
//
1014+
// Variant(a) => ...
1015+
// Variant(_) => ...
1016+
//
1017+
// are conceptually moving into the `Variant`
1018+
// pattern, while the match arm:
1019+
//
1020+
// a @ Variant(_) => ...
1021+
//
1022+
// is *not* moving into the `Variant(_)`.
1023+
// Thus check the `pat_already_bound` flag to
1024+
// distinguish the latter two cases.
1025+
1026+
if !mc.pat_is_already_bound_by_value {
1027+
let mode = copy_or_move(typer.tcx(), cmt_pat.ty, PatBindingMove);
1028+
delegate.consume_pat(pat, cmt_pat, mode);
1029+
}
1030+
}
1031+
}
1032+
}
1033+
10031034
_ => {
10041035
typer.tcx().sess.span_bug(
10051036
pat.span,

src/librustc/middle/mem_categorization.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,11 @@ impl ast_node for ast::Pat {
240240
}
241241

242242
pub struct MemCategorizationContext<'t,TYPER:'t> {
243-
typer: &'t TYPER
243+
typer: &'t TYPER,
244+
245+
// tracks when looking at `pat` in context of `id @ (... pat ...)`
246+
// (it affects whether we move into a wildcard or not).
247+
pub pat_is_already_bound_by_value: bool,
244248
}
245249

246250
pub type McResult<T> = Result<T, ()>;
@@ -378,7 +382,20 @@ macro_rules! if_ok(
378382

379383
impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
380384
pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
381-
MemCategorizationContext { typer: typer }
385+
MemCategorizationContext {
386+
typer: typer,
387+
pat_is_already_bound_by_value: false,
388+
}
389+
}
390+
391+
fn already_bound(&self, mode: ast::BindingMode) -> MemCategorizationContext<'t,TYPER> {
392+
match mode {
393+
ast::BindByRef(_) => *self,
394+
ast::BindByValue(_) => MemCategorizationContext {
395+
pat_is_already_bound_by_value: true,
396+
..*self
397+
}
398+
}
382399
}
383400

384401
fn tcx(&self) -> &'t ty::ctxt<'tcx> {
@@ -1126,8 +1143,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
11261143
}
11271144
}
11281145

1129-
ast::PatIdent(_, _, Some(ref subpat)) => {
1130-
if_ok!(self.cat_pattern(cmt, &**subpat, op));
1146+
ast::PatIdent(binding_mode, _, Some(ref subpat)) => {
1147+
if_ok!(self.already_bound(binding_mode).cat_pattern(cmt, &**subpat, op));
11311148
}
11321149

11331150
ast::PatIdent(_, _, None) => {
@@ -1136,9 +1153,21 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
11361153

11371154
ast::PatStruct(_, ref field_pats, _) => {
11381155
// {f1: p1, ..., fN: pN}
1156+
let downcast_cmt = match self.tcx().def_map.borrow().find(&pat.id) {
1157+
Some(&def::DefVariant(enum_did, variant_did, _)) => {
1158+
// variant{ a: x, b: y, c: z }
1159+
if ty::enum_is_univariant(self.tcx(), enum_did) {
1160+
cmt // univariant, no downcast needed
1161+
} else {
1162+
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
1163+
}
1164+
}
1165+
_ => cmt,
1166+
};
1167+
11391168
for fp in field_pats.iter() {
11401169
let field_ty = if_ok!(self.pat_ty(&*fp.pat)); // see (*2)
1141-
let cmt_field = self.cat_field(pat, cmt.clone(), fp.ident, field_ty);
1170+
let cmt_field = self.cat_field(pat, downcast_cmt.clone(), fp.ident, field_ty);
11421171
if_ok!(self.cat_pattern(cmt_field, &*fp.pat, |x,y,z| op(x,y,z)));
11431172
}
11441173
}
@@ -1377,8 +1406,8 @@ impl Repr for categorization {
13771406
cat_interior(ref cmt, interior) => {
13781407
format!("{}.{}", cmt.cat.repr(tcx), interior.repr(tcx))
13791408
}
1380-
cat_downcast(ref cmt, _) => {
1381-
format!("{}->(enum)", cmt.cat.repr(tcx))
1409+
cat_downcast(ref cmt, ref variant_did) => {
1410+
format!("({}->{})", cmt.cat.repr(tcx), variant_did.repr(tcx))
13821411
}
13831412
cat_discr(ref cmt, _) => {
13841413
cmt.cat.repr(tcx)

0 commit comments

Comments
 (0)