mir-borrowck: describe_lvalue()
can fail if a local doesn't have a name
This commit is contained in:
parent
436ac8928a
commit
503d25cbfd
@ -1343,12 +1343,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
|moi| curr_move_out.contains(moi)).collect::<Vec<_>>();
|
|moi| curr_move_out.contains(moi)).collect::<Vec<_>>();
|
||||||
|
|
||||||
if mois.is_empty() {
|
if mois.is_empty() {
|
||||||
|
let item_msg = match self.describe_lvalue(lvalue) {
|
||||||
|
Some(name) => format!("`{}`", name),
|
||||||
|
None => "value".to_owned()
|
||||||
|
};
|
||||||
self.tcx.cannot_act_on_uninitialized_variable(span,
|
self.tcx.cannot_act_on_uninitialized_variable(span,
|
||||||
desired_action.as_noun(),
|
desired_action.as_noun(),
|
||||||
&self.describe_lvalue(lvalue),
|
&self.describe_lvalue(lvalue)
|
||||||
|
.unwrap_or("_".to_owned()),
|
||||||
Origin::Mir)
|
Origin::Mir)
|
||||||
.span_label(span, format!("use of possibly uninitialized `{}`",
|
.span_label(span, format!("use of possibly uninitialized {}", item_msg))
|
||||||
self.describe_lvalue(lvalue)))
|
|
||||||
.emit();
|
.emit();
|
||||||
} else {
|
} else {
|
||||||
let msg = ""; //FIXME: add "partially " or "collaterally "
|
let msg = ""; //FIXME: add "partially " or "collaterally "
|
||||||
@ -1356,7 +1360,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
let mut err = self.tcx.cannot_act_on_moved_value(span,
|
let mut err = self.tcx.cannot_act_on_moved_value(span,
|
||||||
desired_action.as_noun(),
|
desired_action.as_noun(),
|
||||||
msg,
|
msg,
|
||||||
&self.describe_lvalue(lvalue),
|
&self.describe_lvalue(lvalue)
|
||||||
|
.unwrap_or("_".to_owned()),
|
||||||
Origin::Mir);
|
Origin::Mir);
|
||||||
|
|
||||||
err.span_label(span, format!("value {} here after move",
|
err.span_label(span, format!("value {} here after move",
|
||||||
@ -1381,14 +1386,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
_context: Context,
|
_context: Context,
|
||||||
(lvalue, span): (&Lvalue<'tcx>, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
borrow: &BorrowData<'tcx>) {
|
borrow: &BorrowData<'tcx>) {
|
||||||
|
let value_msg = match self.describe_lvalue(lvalue) {
|
||||||
|
Some(name) => format!("`{}`", name),
|
||||||
|
None => "value".to_owned()
|
||||||
|
};
|
||||||
|
let borrow_msg = match self.describe_lvalue(&borrow.lvalue) {
|
||||||
|
Some(name) => format!("`{}`", name),
|
||||||
|
None => "value".to_owned()
|
||||||
|
};
|
||||||
self.tcx.cannot_move_when_borrowed(span,
|
self.tcx.cannot_move_when_borrowed(span,
|
||||||
&self.describe_lvalue(lvalue),
|
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
|
||||||
Origin::Mir)
|
Origin::Mir)
|
||||||
.span_label(self.retrieve_borrow_span(borrow),
|
.span_label(self.retrieve_borrow_span(borrow),
|
||||||
format!("borrow of `{}` occurs here",
|
format!("borrow of {} occurs here", borrow_msg))
|
||||||
self.describe_lvalue(&borrow.lvalue)))
|
.span_label(span, format!("move out of {} occurs here", value_msg))
|
||||||
.span_label(span, format!("move out of `{}` occurs here",
|
|
||||||
self.describe_lvalue(lvalue)))
|
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1398,8 +1409,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
borrow : &BorrowData<'tcx>) {
|
borrow : &BorrowData<'tcx>) {
|
||||||
|
|
||||||
let mut err = self.tcx.cannot_use_when_mutably_borrowed(
|
let mut err = self.tcx.cannot_use_when_mutably_borrowed(
|
||||||
span, &self.describe_lvalue(lvalue),
|
span,
|
||||||
self.retrieve_borrow_span(borrow), &self.describe_lvalue(&borrow.lvalue),
|
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
|
||||||
|
self.retrieve_borrow_span(borrow),
|
||||||
|
&self.describe_lvalue(&borrow.lvalue).unwrap_or("_".to_owned()),
|
||||||
Origin::Mir);
|
Origin::Mir);
|
||||||
|
|
||||||
err.emit();
|
err.emit();
|
||||||
@ -1488,7 +1501,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
let old_closure_span = self.find_closure_span(issued_span, issued_borrow.location);
|
let old_closure_span = self.find_closure_span(issued_span, issued_borrow.location);
|
||||||
let issued_span = old_closure_span.map(|(args, _)| args).unwrap_or(issued_span);
|
let issued_span = old_closure_span.map(|(args, _)| args).unwrap_or(issued_span);
|
||||||
|
|
||||||
let desc_lvalue = self.describe_lvalue(lvalue);
|
let desc_lvalue = self.describe_lvalue(lvalue).unwrap_or("_".to_owned());
|
||||||
|
|
||||||
// FIXME: supply non-"" `opt_via` when appropriate
|
// FIXME: supply non-"" `opt_via` when appropriate
|
||||||
let mut err = match (gen_borrow_kind, "immutable", "mutable",
|
let mut err = match (gen_borrow_kind, "immutable", "mutable",
|
||||||
@ -1566,7 +1579,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
(lvalue, span): (&Lvalue<'tcx>, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
loan: &BorrowData) {
|
loan: &BorrowData) {
|
||||||
let mut err = self.tcx.cannot_assign_to_borrowed(
|
let mut err = self.tcx.cannot_assign_to_borrowed(
|
||||||
span, self.retrieve_borrow_span(loan), &self.describe_lvalue(lvalue), Origin::Mir);
|
span,
|
||||||
|
self.retrieve_borrow_span(loan),
|
||||||
|
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
|
||||||
|
Origin::Mir);
|
||||||
|
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
@ -1576,12 +1592,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
(lvalue, span): (&Lvalue<'tcx>, Span),
|
(lvalue, span): (&Lvalue<'tcx>, Span),
|
||||||
assigned_span: Span) {
|
assigned_span: Span) {
|
||||||
let mut err = self.tcx.cannot_reassign_immutable(span,
|
let mut err = self.tcx.cannot_reassign_immutable(span,
|
||||||
&self.describe_lvalue(lvalue),
|
&self.describe_lvalue(lvalue).unwrap_or("_".to_owned()),
|
||||||
Origin::Mir);
|
Origin::Mir);
|
||||||
err.span_label(span, "cannot assign twice to immutable variable");
|
err.span_label(span, "cannot assign twice to immutable variable");
|
||||||
if span != assigned_span {
|
if span != assigned_span {
|
||||||
err.span_label(assigned_span, format!("first assignment to `{}`",
|
let value_msg = match self.describe_lvalue(lvalue) {
|
||||||
self.describe_lvalue(lvalue)));
|
Some(name) => format!("`{}`", name),
|
||||||
|
None => "value".to_owned()
|
||||||
|
};
|
||||||
|
err.span_label(assigned_span, format!("first assignment to {}", value_msg));
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
@ -1596,11 +1615,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// End-user visible description of `lvalue`
|
// End-user visible description of `lvalue` if one can be found. If the
|
||||||
fn describe_lvalue(&self, lvalue: &Lvalue<'tcx>) -> String {
|
// lvalue is a temporary for instance, None will be returned.
|
||||||
|
fn describe_lvalue(&self, lvalue: &Lvalue<'tcx>) -> Option<String> {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
self.append_lvalue_to_string(lvalue, &mut buf, false);
|
match self.append_lvalue_to_string(lvalue, &mut buf, false) {
|
||||||
buf
|
Ok(()) => Some(buf),
|
||||||
|
Err(()) => None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If this is a field projection, and the field is being projected from a closure type,
|
/// 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> {
|
|||||||
fn append_lvalue_to_string(&self,
|
fn append_lvalue_to_string(&self,
|
||||||
lvalue: &Lvalue<'tcx>,
|
lvalue: &Lvalue<'tcx>,
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
mut autoderef: bool) {
|
mut autoderef: bool) -> Result<(), ()> {
|
||||||
match *lvalue {
|
match *lvalue {
|
||||||
Lvalue::Local(local) => {
|
Lvalue::Local(local) => {
|
||||||
self.append_local_to_string(local, buf, "_");
|
self.append_local_to_string(local, buf,)?;
|
||||||
}
|
}
|
||||||
Lvalue::Static(ref static_) => {
|
Lvalue::Static(ref static_) => {
|
||||||
buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id)));
|
buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id)));
|
||||||
@ -1653,15 +1675,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if autoderef {
|
if autoderef {
|
||||||
self.append_lvalue_to_string(&proj.base, buf, autoderef);
|
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
|
||||||
} else {
|
} else {
|
||||||
buf.push_str(&"*");
|
buf.push_str(&"*");
|
||||||
self.append_lvalue_to_string(&proj.base, buf, autoderef);
|
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::Downcast(..) => {
|
ProjectionElem::Downcast(..) => {
|
||||||
self.append_lvalue_to_string(&proj.base, buf, autoderef);
|
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
|
||||||
},
|
},
|
||||||
ProjectionElem::Field(field, _ty) => {
|
ProjectionElem::Field(field, _ty) => {
|
||||||
autoderef = true;
|
autoderef = true;
|
||||||
@ -1672,16 +1694,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
buf.push_str(&name);
|
buf.push_str(&name);
|
||||||
} else {
|
} else {
|
||||||
let field_name = self.describe_field(&proj.base, field);
|
let field_name = self.describe_field(&proj.base, field);
|
||||||
self.append_lvalue_to_string(&proj.base, buf, autoderef);
|
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
|
||||||
buf.push_str(&format!(".{}", field_name));
|
buf.push_str(&format!(".{}", field_name));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::Index(index) => {
|
ProjectionElem::Index(index) => {
|
||||||
autoderef = true;
|
autoderef = true;
|
||||||
|
|
||||||
self.append_lvalue_to_string(&proj.base, buf, autoderef);
|
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
|
||||||
buf.push_str("[");
|
buf.push_str("[");
|
||||||
self.append_local_to_string(index, buf, "..");
|
if let Err(_) = self.append_local_to_string(index, buf) {
|
||||||
|
buf.push_str("..");
|
||||||
|
}
|
||||||
buf.push_str("]");
|
buf.push_str("]");
|
||||||
},
|
},
|
||||||
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
|
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
|
||||||
@ -1689,21 +1713,26 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
// Since it isn't possible to borrow an element on a particular index and
|
// Since it isn't possible to borrow an element on a particular index and
|
||||||
// then use another while the borrow is held, don't output indices details
|
// then use another while the borrow is held, don't output indices details
|
||||||
// to avoid confusing the end-user
|
// to avoid confusing the end-user
|
||||||
self.append_lvalue_to_string(&proj.base, buf, autoderef);
|
self.append_lvalue_to_string(&proj.base, buf, autoderef)?;
|
||||||
buf.push_str(&"[..]");
|
buf.push_str(&"[..]");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends end-user visible description of the `local` lvalue to `buf`. If `local` doesn't have
|
// Appends end-user visible description of the `local` lvalue to `buf`. If `local` doesn't have
|
||||||
// a name, then `none_string` is appended instead
|
// a name, then `Err` is returned
|
||||||
fn append_local_to_string(&self, local_index: Local, buf: &mut String, none_string: &str) {
|
fn append_local_to_string(&self, local_index: Local, buf: &mut String) -> Result<(), ()> {
|
||||||
let local = &self.mir.local_decls[local_index];
|
let local = &self.mir.local_decls[local_index];
|
||||||
match local.name {
|
match local.name {
|
||||||
Some(name) => buf.push_str(&format!("{}", name)),
|
Some(name) => {
|
||||||
None => buf.push_str(none_string)
|
buf.push_str(&format!("{}", name));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
None => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user