Skip to content

Commit 503d25c

Browse files
committed
mir-borrowck: describe_lvalue() can fail if a local doesn't have a name
1 parent 436ac89 commit 503d25c

File tree

1 file changed

+62
-33
lines changed

1 file changed

+62
-33
lines changed

src/librustc_mir/borrow_check.rs

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,20 +1343,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13431343
|moi| curr_move_out.contains(moi)).collect::<Vec<_>>();
13441344

13451345
if mois.is_empty() {
1346+
let item_msg = match self.describe_lvalue(lvalue) {
1347+
Some(name) => format!("`{}`", name),
1348+
None => "value".to_owned()
1349+
};
13461350
self.tcx.cannot_act_on_uninitialized_variable(span,
13471351
desired_action.as_noun(),
1348-
&self.describe_lvalue(lvalue),
1352+
&self.describe_lvalue(lvalue)
1353+
.unwrap_or("_".to_owned()),
13491354
Origin::Mir)
1350-
.span_label(span, format!("use of possibly uninitialized `{}`",
1351-
self.describe_lvalue(lvalue)))
1355+
.span_label(span, format!("use of possibly uninitialized {}", item_msg))
13521356
.emit();
13531357
} else {
13541358
let msg = ""; //FIXME: add "partially " or "collaterally "
13551359

13561360
let mut err = self.tcx.cannot_act_on_moved_value(span,
13571361
desired_action.as_noun(),
13581362
msg,
1359-
&self.describe_lvalue(lvalue),
1363+
&self.describe_lvalue(lvalue)
1364+
.unwrap_or("_".to_owned()),
13601365
Origin::Mir);
13611366

13621367
err.span_label(span, format!("value {} here after move",
@@ -1381,14 +1386,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13811386
_context: Context,
13821387
(lvalue, span): (&Lvalue<'tcx>, Span),
13831388
borrow: &BorrowData<'tcx>) {
1389+
let value_msg = match self.describe_lvalue(lvalue) {
1390+
Some(name) => format!("`{}`", name),
1391+
None => "value".to_owned()
1392+
};
1393+
let borrow_msg = match self.describe_lvalue(&borrow.lvalue) {
1394+
Some(name) => format!("`{}`", name),
1395+
None => "value".to_owned()
1396+
};
13841397
self.tcx.cannot_move_when_borrowed(span,
1385-
&self.describe_lvalue(lvalue),
1398+
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
13861399
Origin::Mir)
13871400
.span_label(self.retrieve_borrow_span(borrow),
1388-
format!("borrow of `{}` occurs here",
1389-
self.describe_lvalue(&borrow.lvalue)))
1390-
.span_label(span, format!("move out of `{}` occurs here",
1391-
self.describe_lvalue(lvalue)))
1401+
format!("borrow of {} occurs here", borrow_msg))
1402+
.span_label(span, format!("move out of {} occurs here", value_msg))
13921403
.emit();
13931404
}
13941405

@@ -1398,8 +1409,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13981409
borrow : &BorrowData<'tcx>) {
13991410

14001411
let mut err = self.tcx.cannot_use_when_mutably_borrowed(
1401-
span, &self.describe_lvalue(lvalue),
1402-
self.retrieve_borrow_span(borrow), &self.describe_lvalue(&borrow.lvalue),
1412+
span,
1413+
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
1414+
self.retrieve_borrow_span(borrow),
1415+
&self.describe_lvalue(&borrow.lvalue).unwrap_or("_".to_owned()),
14031416
Origin::Mir);
14041417

14051418
err.emit();
@@ -1488,7 +1501,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
14881501
let old_closure_span = self.find_closure_span(issued_span, issued_borrow.location);
14891502
let issued_span = old_closure_span.map(|(args, _)| args).unwrap_or(issued_span);
14901503

1491-
let desc_lvalue = self.describe_lvalue(lvalue);
1504+
let desc_lvalue = self.describe_lvalue(lvalue).unwrap_or("_".to_owned());
14921505

14931506
// FIXME: supply non-"" `opt_via` when appropriate
14941507
let mut err = match (gen_borrow_kind, "immutable", "mutable",
@@ -1566,7 +1579,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15661579
(lvalue, span): (&Lvalue<'tcx>, Span),
15671580
loan: &BorrowData) {
15681581
let mut err = self.tcx.cannot_assign_to_borrowed(
1569-
span, self.retrieve_borrow_span(loan), &self.describe_lvalue(lvalue), Origin::Mir);
1582+
span,
1583+
self.retrieve_borrow_span(loan),
1584+
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
1585+
Origin::Mir);
15701586

15711587
err.emit();
15721588
}
@@ -1576,12 +1592,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15761592
(lvalue, span): (&Lvalue<'tcx>, Span),
15771593
assigned_span: Span) {
15781594
let mut err = self.tcx.cannot_reassign_immutable(span,
1579-
&self.describe_lvalue(lvalue),
1595+
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
15801596
Origin::Mir);
15811597
err.span_label(span, "cannot assign twice to immutable variable");
15821598
if span != assigned_span {
1583-
err.span_label(assigned_span, format!("first assignment to `{}`",
1584-
self.describe_lvalue(lvalue)));
1599+
let value_msg = match self.describe_lvalue(lvalue) {
1600+
Some(name) => format!("`{}`", name),
1601+
None => "value".to_owned()
1602+
};
1603+
err.span_label(assigned_span, format!("first assignment to {}", value_msg));
15851604
}
15861605
err.emit();
15871606
}
@@ -1596,11 +1615,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15961615
}
15971616

15981617
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1599-
// End-user visible description of `lvalue`
1600-
fn describe_lvalue(&self, lvalue: &Lvalue<'tcx>) -> String {
1618+
// End-user visible description of `lvalue` if one can be found. If the
1619+
// lvalue is a temporary for instance, None will be returned.
1620+
fn describe_lvalue(&self, lvalue: &Lvalue<'tcx>) -> Option<String> {
16011621
let mut buf = String::new();
1602-
self.append_lvalue_to_string(lvalue, &mut buf, false);
1603-
buf
1622+
match self.append_lvalue_to_string(lvalue, &mut buf, false) {
1623+
Ok(()) => Some(buf),
1624+
Err(()) => None
1625+
}
16041626
}
16051627

16061628
/// If this is a field projection, and the field is being projected from a closure type,
@@ -1632,10 +1654,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16321654
fn append_lvalue_to_string(&self,
16331655
lvalue: &Lvalue<'tcx>,
16341656
buf: &mut String,
1635-
mut autoderef: bool) {
1657+
mut autoderef: bool) -> Result<(), ()> {
16361658
match *lvalue {
16371659
Lvalue::Local(local) => {
1638-
self.append_local_to_string(local, buf, "_");
1660+
self.append_local_to_string(local, buf,)?;
16391661
}
16401662
Lvalue::Static(ref static_) => {
16411663
buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id)));
@@ -1653,15 +1675,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16531675
}
16541676
} else {
16551677
if autoderef {
1656-
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1678+
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
16571679
} else {
16581680
buf.push_str(&"*");
1659-
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1681+
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
16601682
}
16611683
}
16621684
},
16631685
ProjectionElem::Downcast(..) => {
1664-
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1686+
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
16651687
},
16661688
ProjectionElem::Field(field, _ty) => {
16671689
autoderef = true;
@@ -1672,38 +1694,45 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16721694
buf.push_str(&name);
16731695
} else {
16741696
let field_name = self.describe_field(&proj.base, field);
1675-
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1697+
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
16761698
buf.push_str(&format!(".{}", field_name));
16771699
}
16781700
},
16791701
ProjectionElem::Index(index) => {
16801702
autoderef = true;
16811703

1682-
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1704+
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
16831705
buf.push_str("[");
1684-
self.append_local_to_string(index, buf, "..");
1706+
if let Err(_) = self.append_local_to_string(index, buf) {
1707+
buf.push_str("..");
1708+
}
16851709
buf.push_str("]");
16861710
},
16871711
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
16881712
autoderef = true;
16891713
// Since it isn't possible to borrow an element on a particular index and
16901714
// then use another while the borrow is held, don't output indices details
16911715
// to avoid confusing the end-user
1692-
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1716+
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
16931717
buf.push_str(&"[..]");
16941718
},
16951719
};
16961720
}
16971721
}
1722+
1723+
Ok(())
16981724
}
16991725

17001726
// Appends end-user visible description of the `local` lvalue to `buf`. If `local` doesn't have
1701-
// a name, then `none_string` is appended instead
1702-
fn append_local_to_string(&self, local_index: Local, buf: &mut String, none_string: &str) {
1727+
// a name, then `Err` is returned
1728+
fn append_local_to_string(&self, local_index: Local, buf: &mut String) -> Result<(), ()> {
17031729
let local = &self.mir.local_decls[local_index];
17041730
match local.name {
1705-
Some(name) => buf.push_str(&format!("{}", name)),
1706-
None => buf.push_str(none_string)
1731+
Some(name) => {
1732+
buf.push_str(&format!("{}", name));
1733+
Ok(())
1734+
},
1735+
None => Err(())
17071736
}
17081737
}
17091738

0 commit comments

Comments
 (0)