mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 19:58:32 +00:00
Improve suggestion to change struct field to &mut
This commit is contained in:
parent
23c2723269
commit
97bf7b934e
@ -229,15 +229,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
} => {
|
} => {
|
||||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||||
|
|
||||||
if let Some((span, message)) = annotate_struct_field(
|
if let Some(span) = get_mut_span_in_struct_field(
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty,
|
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty,
|
||||||
field,
|
field,
|
||||||
) {
|
) {
|
||||||
err.span_suggestion(
|
err.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
"consider changing this to be mutable",
|
"consider changing this to be mutable",
|
||||||
message,
|
"mut ".into(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1059,18 +1059,18 @@ fn is_closure_or_generator(ty: Ty<'_>) -> bool {
|
|||||||
ty.is_closure() || ty.is_generator()
|
ty.is_closure() || ty.is_generator()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a suggestion to a struct definition given a field access to a local.
|
/// Given a field that needs to be mutuable, returns a span where the mut could go.
|
||||||
/// This function expects the local to be a reference to a struct in order to produce a suggestion.
|
/// This function expects the local to be a reference to a struct in order to produce a span.
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// LL | s: &'a String
|
/// LL | s: &'a String
|
||||||
/// | ---------- use `&'a mut String` here to make mutable
|
/// | ^ returns a span pointing here
|
||||||
/// ```
|
/// ```
|
||||||
fn annotate_struct_field<'tcx>(
|
fn get_mut_span_in_struct_field<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
field: &mir::Field,
|
field: &mir::Field,
|
||||||
) -> Option<(Span, String)> {
|
) -> Option<Span> {
|
||||||
// Expect our local to be a reference to a struct of some kind.
|
// Expect our local to be a reference to a struct of some kind.
|
||||||
if let ty::Ref(_, ty, _) = ty.kind() {
|
if let ty::Ref(_, ty, _) = ty.kind() {
|
||||||
if let ty::Adt(def, _) = ty.kind() {
|
if let ty::Adt(def, _) = ty.kind() {
|
||||||
@ -1081,25 +1081,12 @@ fn annotate_struct_field<'tcx>(
|
|||||||
// Now we're dealing with the actual struct that we're going to suggest a change to,
|
// Now we're dealing with the actual struct that we're going to suggest a change to,
|
||||||
// we can expect a field that is an immutable reference to a type.
|
// we can expect a field that is an immutable reference to a type.
|
||||||
if let hir::Node::Field(field) = node {
|
if let hir::Node::Field(field) = node {
|
||||||
if let hir::TyKind::Rptr(
|
if let hir::TyKind::Rptr(lifetime, hir::MutTy { mutbl: hir::Mutability::Not, .. }) =
|
||||||
lifetime,
|
field.ty.kind
|
||||||
hir::MutTy { mutbl: hir::Mutability::Not, ref ty },
|
|
||||||
) = field.ty.kind
|
|
||||||
{
|
{
|
||||||
// Get the snippets in two parts - the named lifetime (if there is one) and
|
return Some(
|
||||||
// type being referenced, that way we can reconstruct the snippet without loss
|
lifetime.span.with_hi(lifetime.span.hi() + BytePos(1)).shrink_to_hi(),
|
||||||
// of detail.
|
);
|
||||||
let type_snippet = tcx.sess.source_map().span_to_snippet(ty.span).ok()?;
|
|
||||||
let lifetime_snippet = if !lifetime.is_elided() {
|
|
||||||
format!("{} ", tcx.sess.source_map().span_to_snippet(lifetime.span).ok()?)
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
return Some((
|
|
||||||
field.ty.span,
|
|
||||||
format!("&{}mut {}", lifetime_snippet, &*type_snippet,),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
struct Bar<'a> {
|
struct Bar<'a> {
|
||||||
s: &'a String
|
s: &'a String,
|
||||||
|
// use wonky spaces to ensure we are creating the span correctly
|
||||||
|
longer_name: & 'a Vec<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Bar<'a> {
|
impl<'a> Bar<'a> {
|
||||||
fn f(&mut self) {
|
fn f(&mut self) {
|
||||||
self.s.push('x');
|
self.s.push('x');
|
||||||
//~^ ERROR cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
//~^ ERROR cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
||||||
|
|
||||||
|
self.longer_name.push(13);
|
||||||
|
//~^ ERROR cannot borrow `*self.longer_name` as mutable, as it is behind a `&` reference
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,25 @@
|
|||||||
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
||||||
--> $DIR/issue-38147-2.rs:7:9
|
--> $DIR/issue-38147-2.rs:9:9
|
||||||
|
|
|
|
||||||
LL | s: &'a String
|
|
||||||
| ---------- help: consider changing this to be mutable: `&'a mut String`
|
|
||||||
...
|
|
||||||
LL | self.s.push('x');
|
LL | self.s.push('x');
|
||||||
| ^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
| ^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
||||||
|
|
|
||||||
|
help: consider changing this to be mutable
|
||||||
|
|
|
||||||
|
LL | s: &'a mut String,
|
||||||
|
| +++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0596]: cannot borrow `*self.longer_name` as mutable, as it is behind a `&` reference
|
||||||
|
--> $DIR/issue-38147-2.rs:12:9
|
||||||
|
|
|
||||||
|
LL | self.longer_name.push(13);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
||||||
|
|
|
||||||
|
help: consider changing this to be mutable
|
||||||
|
|
|
||||||
|
LL | longer_name: & 'a mut Vec<u8>
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0596`.
|
For more information about this error, try `rustc --explain E0596`.
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
||||||
--> $DIR/issue-38147-3.rs:7:9
|
--> $DIR/issue-38147-3.rs:7:9
|
||||||
|
|
|
|
||||||
LL | s: &'a String
|
|
||||||
| ---------- help: consider changing this to be mutable: `&'a mut String`
|
|
||||||
...
|
|
||||||
LL | self.s.push('x');
|
LL | self.s.push('x');
|
||||||
| ^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
| ^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
||||||
|
|
|
||||||
|
help: consider changing this to be mutable
|
||||||
|
|
|
||||||
|
LL | s: &'a mut String
|
||||||
|
| +++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user