Skip to content

Commit 5e82941

Browse files
committed
Auto merge of #27929 - w00ns:issue-27889-same-field-names, r=pnkfelix
Fix for issue #27889: same field names in enum variants
2 parents da31c14 + 43725dc commit 5e82941

File tree

6 files changed

+69
-21
lines changed

6 files changed

+69
-21
lines changed

src/librustc_borrowck/borrowck/check_loans.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
744744
self.check_if_assigned_path_is_moved(id, span,
745745
use_kind, lp_base);
746746
}
747-
LpExtend(ref lp_base, _, LpInterior(InteriorField(_))) => {
747+
LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => {
748748
match lp_base.to_type().sty {
749749
ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() => {
750750
// In the case where the owner implements drop, then
@@ -770,7 +770,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
770770
self.check_if_assigned_path_is_moved(id, span,
771771
use_kind, lp_base);
772772
}
773-
LpExtend(ref lp_base, _, LpInterior(InteriorElement(..))) |
773+
LpExtend(ref lp_base, _, LpInterior(_, InteriorElement(..))) |
774774
LpExtend(ref lp_base, _, LpDeref(_)) => {
775775
// assigning to `P[i]` requires `P` is initialized
776776
// assigning to `(*P)` requires `P` is initialized

src/librustc_borrowck/borrowck/fragments.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,15 +379,15 @@ fn add_fragment_siblings<'tcx>(this: &MoveData<'tcx>,
379379
// bind.
380380
//
381381
// Anyway, for now: LV[j] is not tracked precisely
382-
LpExtend(_, _, LpInterior(InteriorElement(..))) => {
382+
LpExtend(_, _, LpInterior(_, InteriorElement(..))) => {
383383
let mp = this.move_path(tcx, lp.clone());
384384
gathered_fragments.push(AllButOneFrom(mp));
385385
}
386386

387387
// field access LV.x and tuple access LV#k are the cases
388388
// we are interested in
389389
LpExtend(ref loan_parent, mc,
390-
LpInterior(InteriorField(ref field_name))) => {
390+
LpInterior(_, InteriorField(ref field_name))) => {
391391
let enum_variant_info = match loan_parent.kind {
392392
LpDowncast(ref loan_parent_2, variant_def_id) =>
393393
Some((variant_def_id, loan_parent_2.clone())),
@@ -516,7 +516,7 @@ fn add_fragment_sibling_core<'tcx>(this: &MoveData<'tcx>,
516516
LpVar(..) | LpUpvar(..) | LpExtend(..) => enum_variant_did,
517517
};
518518

519-
let loan_path_elem = LpInterior(InteriorField(new_field_name));
519+
let loan_path_elem = LpInterior(opt_variant_did, InteriorField(new_field_name));
520520
let new_lp_type = match new_field_name {
521521
mc::NamedField(ast_name) =>
522522
tcx.named_element_ty(parent.to_type(), ast_name, opt_variant_did),

src/librustc_borrowck/borrowck/gather_loans/restrictions.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,12 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
9797
// Overwriting the base would not change the type of
9898
// the memory, so no additional restrictions are
9999
// needed.
100+
let opt_variant_id = match cmt_base.cat {
101+
Categorization::Downcast(_, variant_id) => Some(variant_id),
102+
_ => None
103+
};
100104
let result = self.restrict(cmt_base);
101-
self.extend(result, &cmt, LpInterior(i.cleaned()))
105+
self.extend(result, &cmt, LpInterior(opt_variant_id, i.cleaned()))
102106
}
103107

104108
Categorization::StaticItem => {

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,18 @@ impl ToInteriorKind for mc::InteriorKind {
377377
}
378378
}
379379

380+
// This can be:
381+
// - a pointer dereference (`*LV` in README.md)
382+
// - a field reference, with an optional definition of the containing
383+
// enum variant (`LV.f` in README.md)
384+
// `DefId` is present when the field is part of struct that is in
385+
// a variant of an enum. For instance in:
386+
// `enum E { X { foo: u32 }, Y { foo: u32 }}`
387+
// each `foo` is qualified by the definitition id of the variant (`X` or `Y`).
380388
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
381389
pub enum LoanPathElem {
382-
LpDeref(mc::PointerKind), // `*LV` in README.md
383-
LpInterior(InteriorKind), // `LV.f` in README.md
390+
LpDeref(mc::PointerKind),
391+
LpInterior(Option<DefId>, InteriorKind),
384392
}
385393

386394
pub fn closure_to_block(closure_id: ast::NodeId,
@@ -413,8 +421,9 @@ impl<'tcx> LoanPath<'tcx> {
413421

414422
fn has_fork(&self, other: &LoanPath<'tcx>) -> bool {
415423
match (&self.kind, &other.kind) {
416-
(&LpExtend(ref base, _, LpInterior(id)), &LpExtend(ref base2, _, LpInterior(id2))) =>
417-
if id == id2 {
424+
(&LpExtend(ref base, _, LpInterior(opt_variant_id, id)),
425+
&LpExtend(ref base2, _, LpInterior(opt_variant_id2, id2))) =>
426+
if id == id2 && opt_variant_id == opt_variant_id2 {
418427
base.has_fork(&**base2)
419428
} else {
420429
true
@@ -428,23 +437,23 @@ impl<'tcx> LoanPath<'tcx> {
428437
fn depth(&self) -> usize {
429438
match self.kind {
430439
LpExtend(ref base, _, LpDeref(_)) => base.depth(),
431-
LpExtend(ref base, _, LpInterior(_)) => base.depth() + 1,
440+
LpExtend(ref base, _, LpInterior(_, _)) => base.depth() + 1,
432441
_ => 0,
433442
}
434443
}
435444

436445
fn common(&self, other: &LoanPath<'tcx>) -> Option<LoanPath<'tcx>> {
437446
match (&self.kind, &other.kind) {
438-
(&LpExtend(ref base, a, LpInterior(id)),
439-
&LpExtend(ref base2, _, LpInterior(id2))) => {
440-
if id == id2 {
447+
(&LpExtend(ref base, a, LpInterior(opt_variant_id, id)),
448+
&LpExtend(ref base2, _, LpInterior(opt_variant_id2, id2))) => {
449+
if id == id2 && opt_variant_id == opt_variant_id2 {
441450
base.common(&**base2).map(|x| {
442451
let xd = x.depth();
443452
if base.depth() == xd && base2.depth() == xd {
444453
assert_eq!(base.ty, base2.ty);
445454
assert_eq!(self.ty, other.ty);
446455
LoanPath {
447-
kind: LpExtend(Rc::new(x), a, LpInterior(id)),
456+
kind: LpExtend(Rc::new(x), a, LpInterior(opt_variant_id, id)),
448457
ty: self.ty,
449458
}
450459
} else {
@@ -509,7 +518,11 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
509518

510519
Categorization::Interior(ref cmt_base, ik) => {
511520
opt_loan_path(cmt_base).map(|lp| {
512-
new_lp(LpExtend(lp, cmt.mutbl, LpInterior(ik.cleaned())))
521+
let opt_variant_id = match cmt_base.cat {
522+
Categorization::Downcast(_, did) => Some(did),
523+
_ => None
524+
};
525+
new_lp(LpExtend(lp, cmt.mutbl, LpInterior(opt_variant_id, ik.cleaned())))
513526
})
514527
}
515528

@@ -1068,7 +1081,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
10681081
}
10691082

10701083

1071-
LpExtend(ref lp_base, _, LpInterior(InteriorField(fname))) => {
1084+
LpExtend(ref lp_base, _, LpInterior(_, InteriorField(fname))) => {
10721085
self.append_autoderefd_loan_path_to_string(&**lp_base, out);
10731086
match fname {
10741087
mc::NamedField(fname) => {
@@ -1082,7 +1095,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
10821095
}
10831096
}
10841097

1085-
LpExtend(ref lp_base, _, LpInterior(InteriorElement(..))) => {
1098+
LpExtend(ref lp_base, _, LpInterior(_, InteriorElement(..))) => {
10861099
self.append_autoderefd_loan_path_to_string(&**lp_base, out);
10871100
out.push_str("[..]");
10881101
}
@@ -1210,7 +1223,7 @@ impl<'tcx> fmt::Debug for LoanPath<'tcx> {
12101223
write!(f, "{:?}.*", lp)
12111224
}
12121225

1213-
LpExtend(ref lp, _, LpInterior(ref interior)) => {
1226+
LpExtend(ref lp, _, LpInterior(_, ref interior)) => {
12141227
write!(f, "{:?}.{:?}", lp, interior)
12151228
}
12161229
}
@@ -1242,7 +1255,7 @@ impl<'tcx> fmt::Display for LoanPath<'tcx> {
12421255
write!(f, "{}.*", lp)
12431256
}
12441257

1245-
LpExtend(ref lp, _, LpInterior(ref interior)) => {
1258+
LpExtend(ref lp, _, LpInterior(_, ref interior)) => {
12461259
write!(f, "{}.{:?}", lp, interior)
12471260
}
12481261
}

src/librustc_borrowck/borrowck/move_data.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ fn loan_path_is_precise(loan_path: &LoanPath) -> bool {
195195
LpVar(_) | LpUpvar(_) => {
196196
true
197197
}
198-
LpExtend(_, _, LpInterior(InteriorKind::InteriorElement(..))) => {
198+
LpExtend(_, _, LpInterior(_, InteriorKind::InteriorElement(..))) => {
199199
// Paths involving element accesses a[i] do not refer to a unique
200200
// location, as there is no accurate tracking of the indices.
201201
//

src/test/run-pass/issue-27889.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2015 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+
// Test that a field can have the same name in different variants
12+
// of an enum
13+
// FIXME #27889
14+
15+
pub enum Foo {
16+
X { foo: u32 },
17+
Y { foo: u32 }
18+
}
19+
20+
pub fn foo(mut x: Foo) {
21+
let mut y = None;
22+
let mut z = None;
23+
if let Foo::X { ref foo } = x {
24+
z = Some(foo);
25+
}
26+
if let Foo::Y { ref mut foo } = x {
27+
y = Some(foo);
28+
}
29+
}
30+
31+
fn main() {}

0 commit comments

Comments
 (0)