Skip to content

Commit 2d1dce8

Browse files
csmoespastorino
authored andcommitted
rewrite place in move_errs
1 parent 7f084ec commit 2d1dce8

File tree

1 file changed

+114
-101
lines changed

1 file changed

+114
-101
lines changed

src/librustc_mir/borrow_check/move_errors.rs

Lines changed: 114 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -111,39 +111,42 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
111111
// If that ever stops being the case, then the ever initialized
112112
// flow could be used.
113113
if let Some(StatementKind::Assign(
114-
Place::Local(local),
114+
place,
115115
box Rvalue::Use(Operand::Move(move_from)),
116116
)) = self.mir.basic_blocks()[location.block]
117117
.statements
118118
.get(location.statement_index)
119119
.map(|stmt| &stmt.kind)
120120
{
121-
let local_decl = &self.mir.local_decls[*local];
122-
// opt_match_place is the
123-
// match_span is the span of the expression being matched on
124-
// match *x.y { ... } match_place is Some(*x.y)
125-
// ^^^^ match_span is the span of *x.y
126-
//
127-
// opt_match_place is None for let [mut] x = ... statements,
128-
// whether or not the right-hand side is a place expression
129-
if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
130-
opt_match_place: Some((ref opt_match_place, match_span)),
131-
binding_mode: _,
132-
opt_ty_info: _,
133-
pat_span: _,
134-
}))) = local_decl.is_user_variable
135-
{
136-
self.append_binding_error(
137-
grouped_errors,
138-
kind,
139-
original_path,
140-
move_from,
141-
*local,
142-
opt_match_place,
143-
match_span,
144-
stmt_source_info.span,
145-
);
146-
return;
121+
let neo_place = self.infcx.tcx.as_new_place(&place);
122+
if let Some(PlaceBase::Local(local)) = neo_place.as_place_base() {
123+
let local_decl = &self.mir.local_decls[*local];
124+
// opt_match_place is the
125+
// match_span is the span of the expression being matched on
126+
// match *x.y { ... } match_place is Some(*x.y)
127+
// ^^^^ match_span is the span of *x.y
128+
//
129+
// opt_match_place is None for let [mut] x = ... statements,
130+
// whether or not the right-hand side is a place expression
131+
if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
132+
opt_match_place: Some((ref opt_match_place, match_span)),
133+
binding_mode: _,
134+
opt_ty_info: _,
135+
pat_span: _,
136+
}))) = local_decl.is_user_variable
137+
{
138+
self.append_binding_error(
139+
grouped_errors,
140+
kind,
141+
original_path,
142+
move_from,
143+
*local,
144+
opt_match_place,
145+
match_span,
146+
stmt_source_info.span,
147+
);
148+
return;
149+
}
147150
}
148151
}
149152
grouped_errors.push(GroupedMoveError::OtherIllegalMove {
@@ -269,12 +272,15 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
269272
// Inspect the type of the content behind the
270273
// borrow to provide feedback about why this
271274
// was a move rather than a copy.
272-
let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
275+
let neo_place = self.infcx.tcx.as_new_place(&place);
276+
let ty = neo_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
277+
273278
let is_upvar_field_projection =
274279
self.prefixes(&original_path, PrefixSet::All)
275280
.map(|p| self.infcx.tcx.as_new_place(&p))
276281
.any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
277-
.is_some());
282+
.is_some()
283+
);
278284
debug!("report: ty={:?}", ty);
279285
match ty.sty {
280286
ty::Array(..) | ty::Slice(..) =>
@@ -354,52 +360,54 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
354360
err: &mut DiagnosticBuilder<'a>,
355361
span: Span,
356362
) {
357-
let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap();
358-
match error {
359-
GroupedMoveError::MovesFromPlace {
360-
mut binds_to,
361-
move_from,
362-
..
363-
} => {
364-
let try_remove_deref = match move_from {
365-
Place::Projection(box PlaceProjection {
366-
elem: ProjectionElem::Deref,
367-
..
368-
}) => true,
369-
_ => false,
370-
};
371-
if try_remove_deref && snippet.starts_with('*') {
372-
// The snippet doesn't start with `*` in (e.g.) index
373-
// expressions `a[b]`, which roughly desugar to
374-
// `*Index::index(&a, b)` or
375-
// `*IndexMut::index_mut(&mut a, b)`.
376-
err.span_suggestion(
377-
span,
378-
"consider removing the `*`",
379-
snippet[1..].to_owned(),
380-
Applicability::Unspecified,
381-
);
382-
} else {
383-
err.span_suggestion(
384-
span,
385-
"consider borrowing here",
386-
format!("&{}", snippet),
387-
Applicability::Unspecified,
388-
);
389-
}
363+
if let Ok(snippet) = self.infcx.tcx.sess
364+
.source_map().span_to_snippet(span) {
365+
match error {
366+
GroupedMoveError::MovesFromPlace {
367+
mut binds_to,
368+
move_from,
369+
..
370+
} => {
371+
let try_remove_deref = match move_from {
372+
Place::Projection(box PlaceProjection {
373+
elem: ProjectionElem::Deref,
374+
..
375+
}) => true,
376+
_ => false,
377+
};
378+
if try_remove_deref && snippet.starts_with('*') {
379+
// The snippet doesn't start with `*` in (e.g.) index
380+
// expressions `a[b]`, which roughly desugar to
381+
// `*Index::index(&a, b)` or
382+
// `*IndexMut::index_mut(&mut a, b)`.
383+
err.span_suggestion(
384+
span,
385+
"consider removing the `*`",
386+
snippet[1..].to_owned(),
387+
Applicability::Unspecified,
388+
);
389+
} else {
390+
err.span_suggestion(
391+
span,
392+
"consider borrowing here",
393+
format!("&{}", snippet),
394+
Applicability::Unspecified,
395+
);
396+
}
390397

391-
binds_to.sort();
392-
binds_to.dedup();
393-
self.add_move_error_details(err, &binds_to);
394-
}
395-
GroupedMoveError::MovesFromValue { mut binds_to, .. } => {
396-
binds_to.sort();
397-
binds_to.dedup();
398-
self.add_move_error_suggestions(err, &binds_to);
399-
self.add_move_error_details(err, &binds_to);
398+
binds_to.sort();
399+
binds_to.dedup();
400+
self.add_move_error_details(err, &binds_to);
401+
}
402+
GroupedMoveError::MovesFromValue { mut binds_to, .. } => {
403+
binds_to.sort();
404+
binds_to.dedup();
405+
self.add_move_error_suggestions(err, &binds_to);
406+
self.add_move_error_details(err, &binds_to);
407+
}
408+
// No binding. Nothing to suggest.
409+
GroupedMoveError::OtherIllegalMove { .. } => (),
400410
}
401-
// No binding. Nothing to suggest.
402-
GroupedMoveError::OtherIllegalMove { .. } => (),
403411
}
404412
}
405413

@@ -417,27 +425,28 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
417425
..
418426
}))
419427
) = bind_to.is_user_variable {
420-
let pat_snippet = self.infcx.tcx.sess.source_map()
421-
.span_to_snippet(pat_span)
422-
.unwrap();
423-
if pat_snippet.starts_with('&') {
424-
let pat_snippet = pat_snippet[1..].trim_start();
425-
let suggestion;
426-
let to_remove;
427-
if pat_snippet.starts_with("mut")
428-
&& pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
429-
{
430-
suggestion = pat_snippet["mut".len()..].trim_start();
431-
to_remove = "&mut";
432-
} else {
433-
suggestion = pat_snippet;
434-
to_remove = "&";
428+
if let Ok(pat_snippet) = self.infcx.tcx.sess
429+
.source_map()
430+
.span_to_snippet(pat_span) {
431+
if pat_snippet.starts_with('&') {
432+
let pat_snippet = pat_snippet[1..].trim_start();
433+
let suggestion;
434+
let to_remove;
435+
if pat_snippet.starts_with("mut")
436+
&& pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
437+
{
438+
suggestion = pat_snippet["mut".len()..].trim_start();
439+
to_remove = "&mut";
440+
} else {
441+
suggestion = pat_snippet;
442+
to_remove = "&";
443+
}
444+
suggestions.push((
445+
pat_span,
446+
to_remove,
447+
suggestion.to_owned(),
448+
));
435449
}
436-
suggestions.push((
437-
pat_span,
438-
to_remove,
439-
suggestion.to_owned(),
440-
));
441450
}
442451
}
443452
}
@@ -536,7 +545,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
536545
// We're only interested in assignments (in particular, where the
537546
// assignment came from - was it an `Rc` or `Arc`?).
538547
if let StatementKind::Assign(_, box Rvalue::Ref(_, _, source)) = &stmt.kind {
539-
let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
548+
let neo_place = self.infcx.tcx.as_new_place(source);
549+
let ty = neo_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
540550
let ty = match ty.sty {
541551
ty::TyKind::Ref(_, ty, _) => ty,
542552
_ => ty,
@@ -560,8 +570,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
560570
Operand::Copy(place) | Operand::Move(place) => place,
561571
_ => continue,
562572
};
563-
564-
let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
573+
let neo_place = self.infcx.tcx.as_new_place(&source);
574+
let ty = neo_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
565575
let ty = match ty.sty {
566576
ty::TyKind::Ref(_, ty, _) => ty,
567577
_ => ty,
@@ -583,11 +593,14 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
583593
// If we didn't find an `Arc` or an `Rc`, then check specifically for
584594
// a dereference of a place that has the type of a raw pointer.
585595
// We can't use `place.ty(..).to_ty(..)` here as that strips away the raw pointer.
586-
if let Place::Projection(box Projection {
587-
base,
588-
elem: ProjectionElem::Deref,
589-
}) = place {
590-
if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() {
596+
let neo_place = self.infcx.tcx.as_new_place(&place);
597+
let place_tys = neo_place.place_tys(&self.mir, self.infcx.tcx);
598+
if let Some(&ProjectionElem::Deref) = neo_place.elems.last() {
599+
// Given place
600+
// base.[a, b, c]
601+
// ^-- deref
602+
// ^^^^^^^^^^
603+
if place_tys[place_tys.len() - 2].to_ty(self.infcx.tcx).is_unsafe_ptr() {
591604
return BorrowedContentSource::DerefRawPointer;
592605
}
593606
}

0 commit comments

Comments
 (0)