Skip to content

Commit ad612d6

Browse files
committed
Fix erroneous error note when using field after move
1 parent 01dbfda commit ad612d6

File tree

9 files changed

+86
-33
lines changed

9 files changed

+86
-33
lines changed

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
680680
let mut err = self.cannot_act_on_moved_value(use_span,
681681
verb,
682682
msg,
683-
&format!("{}", nl),
683+
Some(format!("{}", nl)),
684684
Origin::Ast);
685685
let need_note = match lp.ty.sty {
686686
ty::TypeVariants::TyClosure(id, _) => {

src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
5252

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

55-
let item_msg = match self.describe_place(place) {
55+
let item_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) {
5656
Some(name) => format!("`{}`", name),
5757
None => "value".to_owned(),
5858
};
5959
self.tcx
6060
.cannot_act_on_uninitialized_variable(
6161
span,
6262
desired_action.as_noun(),
63-
&self.describe_place(place).unwrap_or("_".to_owned()),
63+
&self.describe_place_with_options(place, IncludingDowncast(true)).unwrap_or("_".to_owned()),
6464
Origin::Mir,
6565
)
6666
.span_label(span, format!("use of possibly uninitialized {}", item_msg))
@@ -72,14 +72,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
7272
span,
7373
desired_action.as_noun(),
7474
msg,
75-
&self.describe_place(place).unwrap_or("_".to_owned()),
75+
self.describe_place_with_options(&place, IncludingDowncast(true)),
7676
Origin::Mir,
7777
);
7878

7979
let mut is_loop_move = false;
80-
for moi in mois {
80+
for moi in &mois {
8181
let move_msg = ""; //FIXME: add " (into closure)"
82-
let move_span = self.mir.source_info(self.move_data.moves[*moi].source).span;
82+
let move_span = self.mir.source_info(self.move_data.moves[**moi].source).span;
8383
if span == move_span {
8484
err.span_label(
8585
span,
@@ -116,16 +116,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
116116
};
117117

118118
if needs_note {
119-
let note_msg = match self.describe_place(place) {
120-
Some(name) => format!("`{}`", name),
121-
None => "value".to_owned(),
122-
};
119+
let mpi = self.move_data.moves[*mois[0]].path;
120+
let place = &self.move_data.move_paths[mpi].place;
121+
122+
if let Some(ty) = self.retrieve_type_for_place(place) {
123+
let note_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) {
124+
Some(name) => format!("`{}`", name),
125+
None => "value".to_owned(),
126+
};
123127

124-
err.note(&format!(
125-
"move occurs because {} has type `{}`, \
126-
which does not implement the `Copy` trait",
127-
note_msg, ty
128-
));
128+
err.note(&format!(
129+
"move occurs because {} has type `{}`, \
130+
which does not implement the `Copy` trait",
131+
note_msg, ty
132+
));
133+
}
129134
}
130135
}
131136

@@ -654,12 +659,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
654659
}
655660
}
656661

662+
pub(super) struct IncludingDowncast(bool);
663+
657664
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
658665
// End-user visible description of `place` if one can be found. If the
659666
// place is a temporary for instance, None will be returned.
660667
pub(super) fn describe_place(&self, place: &Place<'tcx>) -> Option<String> {
668+
self.describe_place_with_options(place, IncludingDowncast(false))
669+
}
670+
671+
// End-user visible description of `place` if one can be found. If the
672+
// place is a temporary for instance, None will be returned.
673+
// `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is
674+
// `Downcast` and `IncludingDowncast` is true
675+
pub(super) fn describe_place_with_options(&self, place: &Place<'tcx>, including_downcast: IncludingDowncast) -> Option<String> {
661676
let mut buf = String::new();
662-
match self.append_place_to_string(place, &mut buf, false) {
677+
match self.append_place_to_string(place, &mut buf, false, &including_downcast) {
663678
Ok(()) => Some(buf),
664679
Err(()) => None,
665680
}
@@ -671,6 +686,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
671686
place: &Place<'tcx>,
672687
buf: &mut String,
673688
mut autoderef: bool,
689+
including_downcast: &IncludingDowncast,
674690
) -> Result<(), ()> {
675691
match *place {
676692
Place::Local(local) => {
@@ -692,15 +708,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
692708
}
693709
} else {
694710
if autoderef {
695-
self.append_place_to_string(&proj.base, buf, autoderef)?;
711+
self.append_place_to_string(&proj.base, buf, autoderef, &including_downcast)?;
696712
} else {
697713
buf.push_str(&"*");
698-
self.append_place_to_string(&proj.base, buf, autoderef)?;
714+
self.append_place_to_string(&proj.base, buf, autoderef, &including_downcast)?;
699715
}
700716
}
701717
}
702718
ProjectionElem::Downcast(..) => {
703-
self.append_place_to_string(&proj.base, buf, autoderef)?;
719+
self.append_place_to_string(&proj.base, buf, autoderef, &including_downcast)?;
720+
if including_downcast.0 {
721+
return Err(());
722+
}
704723
}
705724
ProjectionElem::Field(field, _ty) => {
706725
autoderef = true;
@@ -711,14 +730,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
711730
buf.push_str(&name);
712731
} else {
713732
let field_name = self.describe_field(&proj.base, field);
714-
self.append_place_to_string(&proj.base, buf, autoderef)?;
733+
self.append_place_to_string(&proj.base, buf, autoderef, &including_downcast)?;
715734
buf.push_str(&format!(".{}", field_name));
716735
}
717736
}
718737
ProjectionElem::Index(index) => {
719738
autoderef = true;
720739

721-
self.append_place_to_string(&proj.base, buf, autoderef)?;
740+
self.append_place_to_string(&proj.base, buf, autoderef, &including_downcast)?;
722741
buf.push_str("[");
723742
if let Err(_) = self.append_local_to_string(index, buf) {
724743
buf.push_str("..");
@@ -730,7 +749,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
730749
// Since it isn't possible to borrow an element on a particular index and
731750
// then use another while the borrow is held, don't output indices details
732751
// to avoid confusing the end-user
733-
self.append_place_to_string(&proj.base, buf, autoderef)?;
752+
self.append_place_to_string(&proj.base, buf, autoderef, &including_downcast)?;
734753
buf.push_str(&"[..]");
735754
}
736755
};

src/librustc_mir/util/borrowck_errors.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,14 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
356356
use_span: Span,
357357
verb: &str,
358358
optional_adverb_for_moved: &str,
359-
moved_path: &str,
359+
moved_path: Option<String>,
360360
o: Origin)
361361
-> DiagnosticBuilder<'cx>
362362
{
363+
let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or("".to_owned());
364+
363365
let err = struct_span_err!(self, use_span, E0382,
364-
"{} of {}moved value: `{}`{OGN}",
366+
"{} of {}moved value{}{OGN}",
365367
verb, optional_adverb_for_moved, moved_path, OGN=o);
366368

367369
self.cancel_if_wrong_origin(err, o)

src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | //~^ value moved here
77
LL | let _y = a.y; //~ ERROR use of moved
88
| ^^^ value used here after move
99
|
10-
= note: move occurs because `a.y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
10+
= note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
1111

1212
error[E0382]: use of moved value: `a.y`
1313
--> $DIR/borrowck-box-insensitivity.rs:108:14
@@ -18,7 +18,7 @@ LL | //~^ value moved here
1818
LL | let _y = a.y; //~ ERROR use of collaterally moved
1919
| ^^^ value used here after move
2020
|
21-
= note: move occurs because `a.y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
21+
= note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
2222

2323
error: aborting due to 2 previous errors
2424

src/test/ui/borrowck/issue-41962.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub fn main(){
2020
//~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382]
2121
//~| ERROR use of moved value: `maybe` (Mir) [E0382]
2222
//~| ERROR use of moved value: `maybe` (Mir) [E0382]
23-
//~| ERROR use of moved value: `maybe.0` (Mir) [E0382]
23+
//~| ERROR use of moved value (Mir) [E0382]
2424
//~| ERROR borrow of moved value: `maybe` (Mir) [E0382]
2525
}
2626
}

src/test/ui/borrowck/issue-41962.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ LL | if let Some(thing) = maybe {
2626
LL | | }
2727
| |_________^ value used here after move
2828
|
29-
= note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
29+
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
3030

3131
error[E0382]: borrow of moved value: `maybe` (Mir)
3232
--> $DIR/issue-41962.rs:17:9
@@ -38,7 +38,7 @@ LL | if let Some(thing) = maybe {
3838
LL | | }
3939
| |_________^ value borrowed here after move
4040
|
41-
= note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
41+
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
4242

4343
error[E0382]: use of moved value: `maybe` (Mir)
4444
--> $DIR/issue-41962.rs:17:16
@@ -49,15 +49,15 @@ LL | if let Some(thing) = maybe {
4949
| | value moved here
5050
| value used here after move
5151
|
52-
= note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
52+
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
5353

54-
error[E0382]: use of moved value: `maybe.0` (Mir)
54+
error[E0382]: use of moved value (Mir)
5555
--> $DIR/issue-41962.rs:17:21
5656
|
5757
LL | if let Some(thing) = maybe {
5858
| ^^^^^ value moved here in previous iteration of loop
5959
|
60-
= note: move occurs because `maybe.0` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
60+
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
6161

6262
error: aborting due to 6 previous errors
6363

src/test/ui/moves-based-on-type-match-bindings.nll.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | Foo {f} => {}
77
LL | touch(&x); //~ ERROR use of partially moved value: `x`
88
| ^^ value borrowed here after move
99
|
10-
= note: move occurs because `x` has type `Foo<std::string::String>`, which does not implement the `Copy` trait
10+
= note: move occurs because `x.f` has type `std::string::String`, which does not implement the `Copy` trait
1111

1212
error: aborting due to previous error
1313

src/test/ui/nll/issue-51512.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2018 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+
#![allow(warnings)]
12+
#![feature(nll)]
13+
14+
fn main() {
15+
let range = 0..1;
16+
let r = range;
17+
let x = range.start;
18+
//~^ ERROR use of moved value: `range.start` [E0382]
19+
}

src/test/ui/nll/issue-51512.stderr

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0382]: use of moved value: `range.start`
2+
--> $DIR/issue-51512.rs:17:13
3+
|
4+
LL | let r = range;
5+
| ----- value moved here
6+
LL | let x = range.start;
7+
| ^^^^^^^^^^^ value used here after move
8+
|
9+
= note: move occurs because `range` has type `std::ops::Range<i32>`, which does not implement the `Copy` trait
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0382`.

0 commit comments

Comments
 (0)