Skip to content

Commit fa26421

Browse files
committed
Auto merge of #45938 - vramana:fix-ice-45698, r=arielb1
Fix End-user description not implemented for field access on `TyClosure - [x] Add Tests
2 parents 88a28ff + 5144d32 commit fa26421

File tree

2 files changed

+80
-31
lines changed

2 files changed

+80
-31
lines changed

src/librustc_mir/borrow_check.rs

+56-31
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
10211021
access_lvalue: (ShallowOrDeep, &Lvalue<'tcx>),
10221022
flow_state: &InProgress<'b, 'gcx, 'tcx>,
10231023
mut op: F)
1024-
where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Lvalue) -> Control
1024+
where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Lvalue<'tcx>) -> Control
10251025
{
10261026
let (access, lvalue) = access_lvalue;
10271027

@@ -1248,7 +1248,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
12481248
fn report_use_of_moved_or_uninitialized(&mut self,
12491249
_context: Context,
12501250
desired_action: &str,
1251-
(lvalue, span): (&Lvalue, Span),
1251+
(lvalue, span): (&Lvalue<'tcx>, Span),
12521252
mpi: MovePathIndex,
12531253
curr_move_out: &IdxSetBuf<MoveOutIndex>) {
12541254

@@ -1290,8 +1290,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
12901290

12911291
fn report_move_out_while_borrowed(&mut self,
12921292
_context: Context,
1293-
(lvalue, span): (&Lvalue, Span),
1294-
borrow: &BorrowData) {
1293+
(lvalue, span): (&Lvalue<'tcx>, Span),
1294+
borrow: &BorrowData<'tcx>) {
12951295
self.tcx.cannot_move_when_borrowed(span,
12961296
&self.describe_lvalue(lvalue),
12971297
Origin::Mir)
@@ -1305,8 +1305,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
13051305

13061306
fn report_use_while_mutably_borrowed(&mut self,
13071307
_context: Context,
1308-
(lvalue, span): (&Lvalue, Span),
1309-
borrow : &BorrowData) {
1308+
(lvalue, span): (&Lvalue<'tcx>, Span),
1309+
borrow : &BorrowData<'tcx>) {
13101310

13111311
let mut err = self.tcx.cannot_use_when_mutably_borrowed(
13121312
span, &self.describe_lvalue(lvalue),
@@ -1382,8 +1382,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
13821382

13831383
fn report_conflicting_borrow(&mut self,
13841384
context: Context,
1385-
common_prefix: &Lvalue,
1386-
(lvalue, span): (&Lvalue, Span),
1385+
common_prefix: &Lvalue<'tcx>,
1386+
(lvalue, span): (&Lvalue<'tcx>, Span),
13871387
gen_borrow_kind: BorrowKind,
13881388
issued_borrow: &BorrowData,
13891389
end_issued_loan_span: Option<Span>) {
@@ -1453,7 +1453,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
14531453

14541454
fn report_illegal_mutation_of_borrowed(&mut self,
14551455
_: Context,
1456-
(lvalue, span): (&Lvalue, Span),
1456+
(lvalue, span): (&Lvalue<'tcx>, Span),
14571457
loan: &BorrowData) {
14581458
let mut err = self.tcx.cannot_assign_to_borrowed(
14591459
span, self.retrieve_borrow_span(loan), &self.describe_lvalue(lvalue), Origin::Mir);
@@ -1463,7 +1463,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
14631463

14641464
fn report_illegal_reassignment(&mut self,
14651465
_context: Context,
1466-
(lvalue, span): (&Lvalue, Span),
1466+
(lvalue, span): (&Lvalue<'tcx>, Span),
14671467
assigned_span: Span) {
14681468
self.tcx.cannot_reassign_immutable(span,
14691469
&self.describe_lvalue(lvalue),
@@ -1474,7 +1474,9 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
14741474
.emit();
14751475
}
14761476

1477-
fn report_assignment_to_static(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) {
1477+
fn report_assignment_to_static(&mut self,
1478+
_context: Context,
1479+
(lvalue, span): (&Lvalue<'tcx>, Span)) {
14781480
let mut err = self.tcx.cannot_assign_static(
14791481
span, &self.describe_lvalue(lvalue), Origin::Mir);
14801482
err.emit();
@@ -1483,14 +1485,17 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
14831485

14841486
impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
14851487
// End-user visible description of `lvalue`
1486-
fn describe_lvalue(&self, lvalue: &Lvalue) -> String {
1488+
fn describe_lvalue(&self, lvalue: &Lvalue<'tcx>) -> String {
14871489
let mut buf = String::new();
14881490
self.append_lvalue_to_string(lvalue, &mut buf, None);
14891491
buf
14901492
}
14911493

14921494
// Appends end-user visible description of `lvalue` to `buf`.
1493-
fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String, autoderef: Option<bool>) {
1495+
fn append_lvalue_to_string(&self,
1496+
lvalue: &Lvalue<'tcx>,
1497+
buf: &mut String,
1498+
autoderef: Option<bool>) {
14941499
match *lvalue {
14951500
Lvalue::Local(local) => {
14961501
self.append_local_to_string(local, buf, "_");
@@ -1500,41 +1505,50 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
15001505
}
15011506
Lvalue::Projection(ref proj) => {
15021507
let mut autoderef = autoderef.unwrap_or(false);
1503-
let (prefix, suffix, index_operand) = match proj.elem {
1508+
1509+
match proj.elem {
15041510
ProjectionElem::Deref => {
15051511
if autoderef {
1506-
("", format!(""), None)
1512+
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
15071513
} else {
1508-
("(*", format!(")"), None)
1514+
buf.push_str(&"(*");
1515+
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
1516+
buf.push_str(&")");
15091517
}
15101518
},
1511-
ProjectionElem::Downcast(..) =>
1512-
("", format!(""), None), // (dont emit downcast info)
1519+
ProjectionElem::Downcast(..) => {
1520+
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
1521+
},
15131522
ProjectionElem::Field(field, _ty) => {
15141523
autoderef = true;
1515-
("", format!(".{}", self.describe_field(&proj.base, field.index())), None)
1524+
let is_projection_from_ty_closure = proj.base.ty(self.mir, self.tcx)
1525+
.to_ty(self.tcx).is_closure();
1526+
1527+
let field_name = self.describe_field(&proj.base, field.index());
1528+
if is_projection_from_ty_closure {
1529+
buf.push_str(&format!("{}", field_name));
1530+
} else {
1531+
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
1532+
buf.push_str(&format!(".{}", field_name));
1533+
}
15161534
},
15171535
ProjectionElem::Index(index) => {
15181536
autoderef = true;
1519-
("", format!(""), Some(index))
1537+
1538+
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
1539+
buf.push_str("[");
1540+
self.append_local_to_string(index, buf, "..");
1541+
buf.push_str("]");
15201542
},
15211543
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
15221544
autoderef = true;
15231545
// Since it isn't possible to borrow an element on a particular index and
15241546
// then use another while the borrow is held, don't output indices details
15251547
// to avoid confusing the end-user
1526-
("", format!("[..]"), None)
1548+
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
1549+
buf.push_str(&"[..]");
15271550
},
15281551
};
1529-
buf.push_str(prefix);
1530-
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
1531-
if let Some(index) = index_operand {
1532-
buf.push_str("[");
1533-
self.append_local_to_string(index, buf, "..");
1534-
buf.push_str("]");
1535-
} else {
1536-
buf.push_str(&suffix);
1537-
}
15381552
}
15391553
}
15401554
}
@@ -1549,6 +1563,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
15491563
}
15501564
}
15511565

1566+
// FIXME Instead of passing usize, Field should be passed
15521567
// End-user visible description of the `field_index`nth field of `base`
15531568
fn describe_field(&self, base: &Lvalue, field_index: usize) -> String {
15541569
match *base {
@@ -1600,7 +1615,17 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
16001615
},
16011616
ty::TyArray(ty, _) | ty::TySlice(ty) => {
16021617
self.describe_field_from_ty(&ty, field_index)
1603-
}
1618+
},
1619+
ty::TyClosure(closure_def_id, _) => {
1620+
// Convert the def-id into a node-id. node-ids are only valid for
1621+
// the local code in the current crate, so this returns an `Option` in case
1622+
// the closure comes from another crate. But in that case we wouldn't
1623+
// be borrowck'ing it, so we can just unwrap:
1624+
let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();
1625+
let freevar = self.tcx.with_freevars(node_id, |fv| fv[field_index]);
1626+
1627+
self.tcx.hir.name(freevar.var_id()).to_string()
1628+
}
16041629
_ => {
16051630
// Might need a revision when the fields in trait RFC is implemented
16061631
// (https://github.com/rust-lang/rfcs/pull/1546)

src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs

+24
Original file line numberDiff line numberDiff line change
@@ -327,4 +327,28 @@ fn main() {
327327
_ => panic!("other case")
328328
}
329329
}
330+
// Field from upvar
331+
{
332+
let mut x = 0;
333+
|| {
334+
let y = &mut x;
335+
&mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
336+
//[mir]~^ ERROR cannot borrow `**x` as mutable more than once at a time (Ast)
337+
//[mir]~| ERROR cannot borrow `(*x)` as mutable more than once at a time (Mir)
338+
*y = 1;
339+
};
340+
}
341+
// Field from upvar nested
342+
{
343+
let mut x = 0;
344+
|| {
345+
|| {
346+
let y = &mut x;
347+
&mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
348+
//[mir]~^ ERROR cannot borrow `**x` as mutable more than once at a time (Ast)
349+
//[mir]~| ERROR cannot borrow `(*x)` as mutable more than once at a time (Mir)
350+
*y = 1;
351+
}
352+
};
353+
}
330354
}

0 commit comments

Comments
 (0)