Skip to content

Commit 0193d1f

Browse files
committed
Group move errors before reporting, add suggestions
1 parent 43fce07 commit 0193d1f

File tree

9 files changed

+502
-66
lines changed

9 files changed

+502
-66
lines changed

src/librustc/mir/mod.rs

+39-9
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,8 @@ pub enum LocalKind {
497497
ReturnPointer,
498498
}
499499

500-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
501-
pub struct VarBindingForm {
500+
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
501+
pub struct VarBindingForm<'tcx> {
502502
/// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
503503
pub binding_mode: ty::BindingMode,
504504
/// If an explicit type was provided for this variable binding,
@@ -508,21 +508,49 @@ pub struct VarBindingForm {
508508
/// doing so breaks incremental compilation (as of this writing),
509509
/// while a `Span` does not cause our tests to fail.
510510
pub opt_ty_info: Option<Span>,
511+
/// Place of the RHS of the =, or the subject of the `match` where this
512+
/// variable is initialized. None in the case of `let PATTERN;`.
513+
/// Some((None, ..)) in the case of and `let [mut] x = ...` because
514+
/// (a) the right-hand side isn't evaluated as a place expression.
515+
/// (b) it gives a way to separate this case from the remaining cases
516+
/// for diagnostics.
517+
pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
511518
}
512519

513-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
514-
pub enum BindingForm {
520+
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
521+
pub enum BindingForm<'tcx> {
515522
/// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
516-
Var(VarBindingForm),
523+
Var(VarBindingForm<'tcx>),
517524
/// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
518525
ImplicitSelf,
519526
}
520527

521-
CloneTypeFoldableAndLiftImpls! { BindingForm, }
528+
CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, }
522529

523-
impl_stable_hash_for!(struct self::VarBindingForm { binding_mode, opt_ty_info });
530+
impl_stable_hash_for!(struct self::VarBindingForm<'tcx> {
531+
binding_mode,
532+
opt_ty_info,
533+
opt_match_place
534+
});
535+
536+
mod binding_form_impl {
537+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
538+
use ich::StableHashingContext;
524539

525-
impl_stable_hash_for!(enum self::BindingForm { Var(binding), ImplicitSelf, });
540+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for super::BindingForm<'tcx> {
541+
fn hash_stable<W: StableHasherResult>(&self,
542+
hcx: &mut StableHashingContext<'a>,
543+
hasher: &mut StableHasher<W>) {
544+
use super::BindingForm::*;
545+
::std::mem::discriminant(self).hash_stable(hcx, hasher);
546+
547+
match self {
548+
Var(binding) => binding.hash_stable(hcx, hasher),
549+
ImplicitSelf => (),
550+
}
551+
}
552+
}
553+
}
526554

527555
/// A MIR local.
528556
///
@@ -542,7 +570,7 @@ pub struct LocalDecl<'tcx> {
542570
/// therefore it need not be visible across crates. pnkfelix
543571
/// currently hypothesized we *need* to wrap this in a
544572
/// `ClearCrossCrate` as long as it carries as `HirId`.
545-
pub is_user_variable: Option<ClearCrossCrate<BindingForm>>,
573+
pub is_user_variable: Option<ClearCrossCrate<BindingForm<'tcx>>>,
546574

547575
/// True if this is an internal local
548576
///
@@ -670,6 +698,7 @@ impl<'tcx> LocalDecl<'tcx> {
670698
Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
671699
binding_mode: ty::BindingMode::BindByValue(_),
672700
opt_ty_info: _,
701+
opt_match_place: _,
673702
}))) => true,
674703

675704
// FIXME: might be able to thread the distinction between
@@ -688,6 +717,7 @@ impl<'tcx> LocalDecl<'tcx> {
688717
Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
689718
binding_mode: ty::BindingMode::BindByValue(_),
690719
opt_ty_info: _,
720+
opt_match_place: _,
691721
}))) => true,
692722

693723
Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true,

src/librustc_mir/borrow_check/mod.rs

+2-35
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ use syntax_pos::Span;
3535

3636
use dataflow::indexes::BorrowIndex;
3737
use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex};
38-
use dataflow::move_paths::{IllegalMoveOriginKind, MoveError};
3938
use dataflow::Borrows;
4039
use dataflow::DataflowResultsConsumer;
4140
use dataflow::FlowAtLocation;
@@ -62,6 +61,7 @@ mod path_utils;
6261
crate mod place_ext;
6362
mod prefixes;
6463
mod used_muts;
64+
mod move_errors;
6565

6666
pub(crate) mod nll;
6767

@@ -117,40 +117,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
117117
let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx) {
118118
Ok(move_data) => move_data,
119119
Err((move_data, move_errors)) => {
120-
for move_error in move_errors {
121-
let (span, kind): (Span, IllegalMoveOriginKind) = match move_error {
122-
MoveError::UnionMove { .. } => {
123-
unimplemented!("don't know how to report union move errors yet.")
124-
}
125-
MoveError::IllegalMove {
126-
cannot_move_out_of: o,
127-
} => (o.span, o.kind),
128-
};
129-
let origin = Origin::Mir;
130-
let mut err = match kind {
131-
IllegalMoveOriginKind::Static => {
132-
tcx.cannot_move_out_of(span, "static item", origin)
133-
}
134-
IllegalMoveOriginKind::BorrowedContent { target_ty: ty } => {
135-
// Inspect the type of the content behind the
136-
// borrow to provide feedback about why this
137-
// was a move rather than a copy.
138-
match ty.sty {
139-
ty::TyArray(..) | ty::TySlice(..) => {
140-
tcx.cannot_move_out_of_interior_noncopy(span, ty, None, origin)
141-
}
142-
_ => tcx.cannot_move_out_of(span, "borrowed content", origin),
143-
}
144-
}
145-
IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
146-
tcx.cannot_move_out_of_interior_of_drop(span, ty, origin)
147-
}
148-
IllegalMoveOriginKind::InteriorOfSliceOrArray { ty, is_index } => {
149-
tcx.cannot_move_out_of_interior_noncopy(span, ty, Some(is_index), origin)
150-
}
151-
};
152-
err.emit();
153-
}
120+
move_errors::report_move_errors(&mir, tcx, move_errors, &move_data);
154121
move_data
155122
}
156123
};

0 commit comments

Comments
 (0)