Skip to content

Fix erroneous error note when using field after move #51688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc_borrowck/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
let mut err = self.cannot_act_on_moved_value(use_span,
verb,
msg,
&format!("{}", nl),
Some(format!("{}", nl)),
Origin::Ast);
let need_note = match lp.ty.sty {
ty::TypeVariants::TyClosure(id, _) => {
Expand Down
108 changes: 85 additions & 23 deletions src/librustc_mir/borrow_check/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {

self.moved_error_reported.insert(root_place.clone());

let item_msg = match self.describe_place(place) {
let item_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) {
Some(name) => format!("`{}`", name),
None => "value".to_owned(),
};
self.tcx
.cannot_act_on_uninitialized_variable(
span,
desired_action.as_noun(),
&self.describe_place(place).unwrap_or("_".to_owned()),
&self
.describe_place_with_options(place, IncludingDowncast(true))
.unwrap_or("_".to_owned()),
Origin::Mir,
)
.span_label(span, format!("use of possibly uninitialized {}", item_msg))
Expand All @@ -72,14 +74,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
span,
desired_action.as_noun(),
msg,
&self.describe_place(place).unwrap_or("_".to_owned()),
self.describe_place_with_options(&place, IncludingDowncast(true)),
Origin::Mir,
);

let mut is_loop_move = false;
for moi in mois {
for moi in &mois {
let move_msg = ""; //FIXME: add " (into closure)"
let move_span = self.mir.source_info(self.move_data.moves[*moi].source).span;
let move_span = self
.mir
.source_info(self.move_data.moves[**moi].source)
.span;
if span == move_span {
err.span_label(
span,
Expand Down Expand Up @@ -116,16 +121,23 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
};

if needs_note {
let note_msg = match self.describe_place(place) {
Some(name) => format!("`{}`", name),
None => "value".to_owned(),
};
let mpi = self.move_data.moves[*mois[0]].path;
let place = &self.move_data.move_paths[mpi].place;

if let Some(ty) = self.retrieve_type_for_place(place) {
let note_msg = match self
.describe_place_with_options(place, IncludingDowncast(true))
{
Some(name) => format!("`{}`", name),
None => "value".to_owned(),
};

err.note(&format!(
"move occurs because {} has type `{}`, \
which does not implement the `Copy` trait",
note_msg, ty
));
err.note(&format!(
"move occurs because {} has type `{}`, \
which does not implement the `Copy` trait",
note_msg, ty
));
}
}
}

Expand Down Expand Up @@ -644,8 +656,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let local_decl = &self.mir.local_decls[*local];
if let Some(name) = local_decl.name {
if local_decl.can_be_made_mutable() {
err.span_label(local_decl.source_info.span,
format!("consider changing this to `mut {}`", name));
err.span_label(
local_decl.source_info.span,
format!("consider changing this to `mut {}`", name),
);
}
}
}
Expand All @@ -654,12 +668,26 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}
}

pub(super) struct IncludingDowncast(bool);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's usually a bit more idiomatic to use an enum with the possible states, but this is still an improvement in readibility over a naked Boolean.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think I prefer an enum, was just following @nikomatsakis suggestion. But I'm fine with either.


impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// End-user visible description of `place` if one can be found. If the
// place is a temporary for instance, None will be returned.
pub(super) fn describe_place(&self, place: &Place<'tcx>) -> Option<String> {
self.describe_place_with_options(place, IncludingDowncast(false))
}

// End-user visible description of `place` if one can be found. If the
// place is a temporary for instance, None will be returned.
// `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is
// `Downcast` and `IncludingDowncast` is true
pub(super) fn describe_place_with_options(
&self,
place: &Place<'tcx>,
including_downcast: IncludingDowncast,
) -> Option<String> {
let mut buf = String::new();
match self.append_place_to_string(place, &mut buf, false) {
match self.append_place_to_string(place, &mut buf, false, &including_downcast) {
Ok(()) => Some(buf),
Err(()) => None,
}
Expand All @@ -671,6 +699,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
place: &Place<'tcx>,
buf: &mut String,
mut autoderef: bool,
including_downcast: &IncludingDowncast,
) -> Result<(), ()> {
match *place {
Place::Local(local) => {
Expand All @@ -692,15 +721,33 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}
} else {
if autoderef {
self.append_place_to_string(&proj.base, buf, autoderef)?;
self.append_place_to_string(
&proj.base,
buf,
autoderef,
&including_downcast,
)?;
} else {
buf.push_str(&"*");
self.append_place_to_string(&proj.base, buf, autoderef)?;
self.append_place_to_string(
&proj.base,
buf,
autoderef,
&including_downcast,
)?;
}
}
}
ProjectionElem::Downcast(..) => {
self.append_place_to_string(&proj.base, buf, autoderef)?;
self.append_place_to_string(
&proj.base,
buf,
autoderef,
&including_downcast,
)?;
if including_downcast.0 {
return Err(());
}
}
ProjectionElem::Field(field, _ty) => {
autoderef = true;
Expand All @@ -711,14 +758,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
buf.push_str(&name);
} else {
let field_name = self.describe_field(&proj.base, field);
self.append_place_to_string(&proj.base, buf, autoderef)?;
self.append_place_to_string(
&proj.base,
buf,
autoderef,
&including_downcast,
)?;
buf.push_str(&format!(".{}", field_name));
}
}
ProjectionElem::Index(index) => {
autoderef = true;

self.append_place_to_string(&proj.base, buf, autoderef)?;
self.append_place_to_string(
&proj.base,
buf,
autoderef,
&including_downcast,
)?;
buf.push_str("[");
if let Err(_) = self.append_local_to_string(index, buf) {
buf.push_str("..");
Expand All @@ -730,7 +787,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// 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
// to avoid confusing the end-user
self.append_place_to_string(&proj.base, buf, autoderef)?;
self.append_place_to_string(
&proj.base,
buf,
autoderef,
&including_downcast,
)?;
buf.push_str(&"[..]");
}
};
Expand Down
Loading