1
Fork 0

Do not use a suggestion to change a binding's name to a type

This commit is contained in:
Michael Goulet 2022-06-27 20:23:24 -07:00
parent f4fdcc7e24
commit 8fd73560b3
12 changed files with 50 additions and 43 deletions

View file

@ -434,8 +434,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
match self.local_names[local] { match self.local_names[local] {
Some(name) if !local_decl.from_compiler_desugaring() => { Some(name) if !local_decl.from_compiler_desugaring() => {
let label = match local_decl.local_info.as_ref().unwrap() { let label = match local_decl.local_info.as_deref().unwrap() {
box LocalInfo::User(ClearCrossCrate::Set( LocalInfo::User(ClearCrossCrate::Set(
mir::BindingForm::ImplicitSelf(_), mir::BindingForm::ImplicitSelf(_),
)) => { )) => {
let (span, suggestion) = let (span, suggestion) =
@ -443,7 +443,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
Some((true, span, suggestion)) Some((true, span, suggestion))
} }
box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
mir::VarBindingForm { mir::VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_), binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info, opt_ty_info,
@ -473,20 +473,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// on for loops, RHS points to the iterator part // on for loops, RHS points to the iterator part
Some(DesugaringKind::ForLoop) => { Some(DesugaringKind::ForLoop) => {
self.suggest_similar_mut_method_for_for_loop(&mut err); self.suggest_similar_mut_method_for_for_loop(&mut err);
Some(( err.span_label(opt_assignment_rhs_span.unwrap(), format!(
false, "this iterator yields `{pointer_sigil}` {pointer_desc}s",
opt_assignment_rhs_span.unwrap(), ));
format!( None
"this iterator yields `{SIGIL}` {DESC}s",
SIGIL = pointer_sigil,
DESC = pointer_desc
),
))
} }
// don't create labels for compiler-generated spans // don't create labels for compiler-generated spans
Some(_) => None, Some(_) => None,
None => { None => {
let (span, suggestion) = if name != kw::SelfLower { let label = if name != kw::SelfLower {
suggest_ampmut( suggest_ampmut(
self.infcx.tcx, self.infcx.tcx,
local_decl, local_decl,
@ -501,7 +496,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.. ..
}), }),
))) => { ))) => {
suggest_ampmut_self(self.infcx.tcx, local_decl) let (span, sugg) = suggest_ampmut_self(
self.infcx.tcx,
local_decl,
);
(true, span, sugg)
} }
// explicit self (eg `self: &'a Self`) // explicit self (eg `self: &'a Self`)
_ => suggest_ampmut( _ => suggest_ampmut(
@ -512,12 +511,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
), ),
} }
}; };
Some((true, span, suggestion)) Some(label)
} }
} }
} }
box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
mir::VarBindingForm { mir::VarBindingForm {
binding_mode: ty::BindingMode::BindByReference(_), binding_mode: ty::BindingMode::BindByReference(_),
.. ..
@ -528,7 +527,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.map(|replacement| (true, pattern_span, replacement)) .map(|replacement| (true, pattern_span, replacement))
} }
box LocalInfo::User(ClearCrossCrate::Clear) => { LocalInfo::User(ClearCrossCrate::Clear) => {
bug!("saw cleared local state") bug!("saw cleared local state")
} }
@ -559,7 +558,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
} }
} }
Some((false, err_label_span, message)) => { Some((false, err_label_span, message)) => {
err.span_label(err_label_span, &message); err.span_label(
err_label_span,
&format!(
"consider changing this binding's type to be: `{message}`"
),
);
} }
None => {} None => {}
} }
@ -1004,7 +1008,7 @@ fn suggest_ampmut<'tcx>(
local_decl: &mir::LocalDecl<'tcx>, local_decl: &mir::LocalDecl<'tcx>,
opt_assignment_rhs_span: Option<Span>, opt_assignment_rhs_span: Option<Span>,
opt_ty_info: Option<Span>, opt_ty_info: Option<Span>,
) -> (Span, String) { ) -> (bool, Span, String) {
if let Some(assignment_rhs_span) = opt_assignment_rhs_span if let Some(assignment_rhs_span) = opt_assignment_rhs_span
&& let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) && let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span)
{ {
@ -1028,24 +1032,24 @@ fn suggest_ampmut<'tcx>(
let lt_name = &src[1..ws_pos]; let lt_name = &src[1..ws_pos];
let ty = src[ws_pos..].trim_start(); let ty = src[ws_pos..].trim_start();
if !is_mutbl(ty) { if !is_mutbl(ty) {
return (assignment_rhs_span, format!("&{lt_name} mut {ty}")); return (true, assignment_rhs_span, format!("&{lt_name} mut {ty}"));
} }
} else if let Some(stripped) = src.strip_prefix('&') { } else if let Some(stripped) = src.strip_prefix('&') {
let stripped = stripped.trim_start(); let stripped = stripped.trim_start();
if !is_mutbl(stripped) { if !is_mutbl(stripped) {
return (assignment_rhs_span, format!("&mut {stripped}")); return (true, assignment_rhs_span, format!("&mut {stripped}"));
} }
} }
} }
let highlight_span = match opt_ty_info { let (suggestability, highlight_span) = match opt_ty_info {
// if this is a variable binding with an explicit type, // if this is a variable binding with an explicit type,
// try to highlight that for the suggestion. // try to highlight that for the suggestion.
Some(ty_span) => ty_span, Some(ty_span) => (true, ty_span),
// otherwise, just highlight the span associated with // otherwise, just highlight the span associated with
// the (MIR) LocalDecl. // the (MIR) LocalDecl.
None => local_decl.source_info.span, None => (false, local_decl.source_info.span),
}; };
if let Ok(src) = tcx.sess.source_map().span_to_snippet(highlight_span) if let Ok(src) = tcx.sess.source_map().span_to_snippet(highlight_span)
@ -1053,12 +1057,13 @@ fn suggest_ampmut<'tcx>(
{ {
let lt_name = &src[1..ws_pos]; let lt_name = &src[1..ws_pos];
let ty = &src[ws_pos..]; let ty = &src[ws_pos..];
return (highlight_span, format!("&{} mut{}", lt_name, ty)); return (true, highlight_span, format!("&{} mut{}", lt_name, ty));
} }
let ty_mut = local_decl.ty.builtin_deref(true).unwrap(); let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
assert_eq!(ty_mut.mutbl, hir::Mutability::Not); assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
( (
suggestability,
highlight_span, highlight_span,
if local_decl.ty.is_region_ptr() { if local_decl.ty.is_region_ptr() {
format!("&mut {}", ty_mut.ty) format!("&mut {}", ty_mut.ty)

View file

@ -162,7 +162,11 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
let opt_ty_info; let opt_ty_info;
let self_arg; let self_arg;
if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) { if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) {
opt_ty_info = fn_decl.inputs.get(index).map(|ty| ty.span); opt_ty_info = fn_decl
.inputs
.get(index)
// Make sure that inferred closure args have no type span
.and_then(|ty| if arg.pat.span != ty.span { Some(ty.span) } else { None });
self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() { self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
match fn_decl.implicit_self { match fn_decl.implicit_self {
hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm), hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm),

View file

@ -2,7 +2,7 @@ error[E0594]: cannot assign to `**t1`, which is behind a `&` reference
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5 --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
| |
LL | let t1 = t0; LL | let t1 = t0;
| -- help: consider changing this to be a mutable reference: `&mut &mut isize` | -- consider changing this binding's type to be: `&mut &mut isize`
LL | let p: &isize = &**t0; LL | let p: &isize = &**t0;
LL | **t1 = 22; LL | **t1 = 22;
| ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written | ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written

View file

@ -1,7 +1,7 @@
fn main() { fn main() {
let mut test = Vec::new(); let mut test = Vec::new();
let rofl: &Vec<Vec<i32>> = &mut test; let rofl: &Vec<Vec<i32>> = &mut test;
//~^ HELP consider changing this to be a mutable reference //~^ NOTE consider changing this binding's type to be
rofl.push(Vec::new()); rofl.push(Vec::new());
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@ -15,14 +15,14 @@ fn main() {
#[rustfmt::skip] #[rustfmt::skip]
let x: &usize = &mut{0}; let x: &usize = &mut{0};
//~^ HELP consider changing this to be a mutable reference //~^ NOTE consider changing this binding's type to be
*x = 1; *x = 1;
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference //~^ ERROR cannot assign to `*x`, which is behind a `&` reference
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written //~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
#[rustfmt::skip] #[rustfmt::skip]
let y: &usize = &mut(0); let y: &usize = &mut(0);
//~^ HELP consider changing this to be a mutable reference //~^ NOTE consider changing this binding's type to be
*y = 1; *y = 1;
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference //~^ ERROR cannot assign to `*y`, which is behind a `&` reference
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written //~| NOTE `y` is a `&` reference, so the data it refers to cannot be written

View file

@ -2,7 +2,7 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
--> $DIR/issue-85765.rs:5:5 --> $DIR/issue-85765.rs:5:5
| |
LL | let rofl: &Vec<Vec<i32>> = &mut test; LL | let rofl: &Vec<Vec<i32>> = &mut test;
| ---- help: consider changing this to be a mutable reference: `&mut Vec<Vec<i32>>` | ---- consider changing this binding's type to be: `&mut Vec<Vec<i32>>`
LL | LL |
LL | rofl.push(Vec::new()); LL | rofl.push(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable | ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@ -20,7 +20,7 @@ error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/issue-85765.rs:19:5 --> $DIR/issue-85765.rs:19:5
| |
LL | let x: &usize = &mut{0}; LL | let x: &usize = &mut{0};
| - help: consider changing this to be a mutable reference: `&mut usize` | - consider changing this binding's type to be: `&mut usize`
LL | LL |
LL | *x = 1; LL | *x = 1;
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
@ -29,7 +29,7 @@ error[E0594]: cannot assign to `*y`, which is behind a `&` reference
--> $DIR/issue-85765.rs:26:5 --> $DIR/issue-85765.rs:26:5
| |
LL | let y: &usize = &mut(0); LL | let y: &usize = &mut(0);
| - help: consider changing this to be a mutable reference: `&mut usize` | - consider changing this binding's type to be: `&mut usize`
LL | LL |
LL | *y = 1; LL | *y = 1;
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written

View file

@ -9,7 +9,8 @@ impl TestClient {
fn main() { fn main() {
let client = TestClient; let client = TestClient;
let inner = client.get_inner_ref(); let inner = client.get_inner_ref();
//~^ HELP consider changing this to be a mutable reference //~^ NOTE consider changing this binding's type to be
inner.clear(); inner.clear();
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
//~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
} }

View file

@ -2,7 +2,7 @@ error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference
--> $DIR/issue-91206.rs:13:5 --> $DIR/issue-91206.rs:13:5
| |
LL | let inner = client.get_inner_ref(); LL | let inner = client.get_inner_ref();
| ----- help: consider changing this to be a mutable reference: `&mut Vec<usize>` | ----- consider changing this binding's type to be: `&mut Vec<usize>`
LL | LL |
LL | inner.clear(); LL | inner.clear();
| ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable | ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable

View file

@ -2,7 +2,7 @@ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
--> $DIR/issue-92015.rs:6:5 --> $DIR/issue-92015.rs:6:5
| |
LL | let foo = Some(&0).unwrap(); LL | let foo = Some(&0).unwrap();
| --- help: consider changing this to be a mutable reference: `&mut i32` | --- consider changing this binding's type to be: `&mut i32`
LL | *foo = 1; LL | *foo = 1;
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written | ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written

View file

@ -1,7 +1,7 @@
// This is not exactly right, yet. // This is not exactly right, yet.
// Ideally we should be suggesting `as_mut` for the first case, // Ideally we should be suggesting `as_mut` for the first case,
//and suggesting to change `as_ref` to `as_mut` in the second. // and suggesting to change `as_ref` to `as_mut` in the second.
fn x(cb: &mut Option<&mut dyn FnMut()>) { fn x(cb: &mut Option<&mut dyn FnMut()>) {
cb.map(|cb| cb()); cb.map(|cb| cb());

View file

@ -23,7 +23,7 @@ error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
LL | cb.as_ref().map(|cb| cb()); LL | cb.as_ref().map(|cb| cb());
| -- ^^ `cb` is a `&` reference, so the data it refers to cannot be borrowed as mutable | -- ^^ `cb` is a `&` reference, so the data it refers to cannot be borrowed as mutable
| | | |
| help: consider changing this to be a mutable reference: `&mut &mut dyn FnMut()` | consider changing this binding's type to be: `&mut &mut dyn FnMut()`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -5,8 +5,6 @@ fn main() {
*foo = 32; *foo = 32;
//~^ ERROR cannot assign to `*foo`, which is behind a `&` reference //~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
let bar = foo; let bar = foo;
//~^ HELP consider changing this to be a mutable reference
//~| SUGGESTION &mut i32
*bar = 64; *bar = 64;
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference //~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
} }

View file

@ -8,11 +8,10 @@ LL | *foo = 32;
| ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
--> $DIR/issue-51515.rs:10:5 --> $DIR/issue-51515.rs:8:5
| |
LL | let bar = foo; LL | let bar = foo;
| --- help: consider changing this to be a mutable reference: `&mut i32` | --- consider changing this binding's type to be: `&mut i32`
...
LL | *bar = 64; LL | *bar = 64;
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written