Skip to content

Commit 8fd7356

Browse files
Do not use a suggestion to change a binding's name to a type
1 parent f4fdcc7 commit 8fd7356

12 files changed

+50
-43
lines changed

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+30-25
Original file line numberDiff line numberDiff line change
@@ -434,16 +434,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
434434

435435
match self.local_names[local] {
436436
Some(name) if !local_decl.from_compiler_desugaring() => {
437-
let label = match local_decl.local_info.as_ref().unwrap() {
438-
box LocalInfo::User(ClearCrossCrate::Set(
437+
let label = match local_decl.local_info.as_deref().unwrap() {
438+
LocalInfo::User(ClearCrossCrate::Set(
439439
mir::BindingForm::ImplicitSelf(_),
440440
)) => {
441441
let (span, suggestion) =
442442
suggest_ampmut_self(self.infcx.tcx, local_decl);
443443
Some((true, span, suggestion))
444444
}
445445

446-
box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
446+
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
447447
mir::VarBindingForm {
448448
binding_mode: ty::BindingMode::BindByValue(_),
449449
opt_ty_info,
@@ -473,20 +473,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
473473
// on for loops, RHS points to the iterator part
474474
Some(DesugaringKind::ForLoop) => {
475475
self.suggest_similar_mut_method_for_for_loop(&mut err);
476-
Some((
477-
false,
478-
opt_assignment_rhs_span.unwrap(),
479-
format!(
480-
"this iterator yields `{SIGIL}` {DESC}s",
481-
SIGIL = pointer_sigil,
482-
DESC = pointer_desc
483-
),
484-
))
476+
err.span_label(opt_assignment_rhs_span.unwrap(), format!(
477+
"this iterator yields `{pointer_sigil}` {pointer_desc}s",
478+
));
479+
None
485480
}
486481
// don't create labels for compiler-generated spans
487482
Some(_) => None,
488483
None => {
489-
let (span, suggestion) = if name != kw::SelfLower {
484+
let label = if name != kw::SelfLower {
490485
suggest_ampmut(
491486
self.infcx.tcx,
492487
local_decl,
@@ -501,7 +496,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
501496
..
502497
}),
503498
))) => {
504-
suggest_ampmut_self(self.infcx.tcx, local_decl)
499+
let (span, sugg) = suggest_ampmut_self(
500+
self.infcx.tcx,
501+
local_decl,
502+
);
503+
(true, span, sugg)
505504
}
506505
// explicit self (eg `self: &'a Self`)
507506
_ => suggest_ampmut(
@@ -512,12 +511,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
512511
),
513512
}
514513
};
515-
Some((true, span, suggestion))
514+
Some(label)
516515
}
517516
}
518517
}
519518

520-
box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
519+
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
521520
mir::VarBindingForm {
522521
binding_mode: ty::BindingMode::BindByReference(_),
523522
..
@@ -528,7 +527,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
528527
.map(|replacement| (true, pattern_span, replacement))
529528
}
530529

531-
box LocalInfo::User(ClearCrossCrate::Clear) => {
530+
LocalInfo::User(ClearCrossCrate::Clear) => {
532531
bug!("saw cleared local state")
533532
}
534533

@@ -559,7 +558,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
559558
}
560559
}
561560
Some((false, err_label_span, message)) => {
562-
err.span_label(err_label_span, &message);
561+
err.span_label(
562+
err_label_span,
563+
&format!(
564+
"consider changing this binding's type to be: `{message}`"
565+
),
566+
);
563567
}
564568
None => {}
565569
}
@@ -1004,7 +1008,7 @@ fn suggest_ampmut<'tcx>(
10041008
local_decl: &mir::LocalDecl<'tcx>,
10051009
opt_assignment_rhs_span: Option<Span>,
10061010
opt_ty_info: Option<Span>,
1007-
) -> (Span, String) {
1011+
) -> (bool, Span, String) {
10081012
if let Some(assignment_rhs_span) = opt_assignment_rhs_span
10091013
&& let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span)
10101014
{
@@ -1028,37 +1032,38 @@ fn suggest_ampmut<'tcx>(
10281032
let lt_name = &src[1..ws_pos];
10291033
let ty = src[ws_pos..].trim_start();
10301034
if !is_mutbl(ty) {
1031-
return (assignment_rhs_span, format!("&{lt_name} mut {ty}"));
1035+
return (true, assignment_rhs_span, format!("&{lt_name} mut {ty}"));
10321036
}
10331037
} else if let Some(stripped) = src.strip_prefix('&') {
10341038
let stripped = stripped.trim_start();
10351039
if !is_mutbl(stripped) {
1036-
return (assignment_rhs_span, format!("&mut {stripped}"));
1040+
return (true, assignment_rhs_span, format!("&mut {stripped}"));
10371041
}
10381042
}
10391043
}
10401044

1041-
let highlight_span = match opt_ty_info {
1045+
let (suggestability, highlight_span) = match opt_ty_info {
10421046
// if this is a variable binding with an explicit type,
10431047
// try to highlight that for the suggestion.
1044-
Some(ty_span) => ty_span,
1048+
Some(ty_span) => (true, ty_span),
10451049

10461050
// otherwise, just highlight the span associated with
10471051
// the (MIR) LocalDecl.
1048-
None => local_decl.source_info.span,
1052+
None => (false, local_decl.source_info.span),
10491053
};
10501054

10511055
if let Ok(src) = tcx.sess.source_map().span_to_snippet(highlight_span)
10521056
&& let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(char::is_whitespace))
10531057
{
10541058
let lt_name = &src[1..ws_pos];
10551059
let ty = &src[ws_pos..];
1056-
return (highlight_span, format!("&{} mut{}", lt_name, ty));
1060+
return (true, highlight_span, format!("&{} mut{}", lt_name, ty));
10571061
}
10581062

10591063
let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
10601064
assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
10611065
(
1066+
suggestability,
10621067
highlight_span,
10631068
if local_decl.ty.is_region_ptr() {
10641069
format!("&mut {}", ty_mut.ty)

compiler/rustc_mir_build/src/build/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,11 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
162162
let opt_ty_info;
163163
let self_arg;
164164
if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) {
165-
opt_ty_info = fn_decl.inputs.get(index).map(|ty| ty.span);
165+
opt_ty_info = fn_decl
166+
.inputs
167+
.get(index)
168+
// Make sure that inferred closure args have no type span
169+
.and_then(|ty| if arg.pat.span != ty.span { Some(ty.span) } else { None });
166170
self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
167171
match fn_decl.implicit_self {
168172
hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm),

src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr

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

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
fn main() {
22
let mut test = Vec::new();
33
let rofl: &Vec<Vec<i32>> = &mut test;
4-
//~^ HELP consider changing this to be a mutable reference
4+
//~^ NOTE consider changing this binding's type to be
55
rofl.push(Vec::new());
66
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
77
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@@ -15,14 +15,14 @@ fn main() {
1515

1616
#[rustfmt::skip]
1717
let x: &usize = &mut{0};
18-
//~^ HELP consider changing this to be a mutable reference
18+
//~^ NOTE consider changing this binding's type to be
1919
*x = 1;
2020
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
2121
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
2222

2323
#[rustfmt::skip]
2424
let y: &usize = &mut(0);
25-
//~^ HELP consider changing this to be a mutable reference
25+
//~^ NOTE consider changing this binding's type to be
2626
*y = 1;
2727
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
2828
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
22
--> $DIR/issue-85765.rs:5:5
33
|
44
LL | let rofl: &Vec<Vec<i32>> = &mut test;
5-
| ---- help: consider changing this to be a mutable reference: `&mut Vec<Vec<i32>>`
5+
| ---- consider changing this binding's type to be: `&mut Vec<Vec<i32>>`
66
LL |
77
LL | rofl.push(Vec::new());
88
| ^^^^^^^^^^^^^^^^^^^^^ `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
2020
--> $DIR/issue-85765.rs:19:5
2121
|
2222
LL | let x: &usize = &mut{0};
23-
| - help: consider changing this to be a mutable reference: `&mut usize`
23+
| - consider changing this binding's type to be: `&mut usize`
2424
LL |
2525
LL | *x = 1;
2626
| ^^^^^^ `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
2929
--> $DIR/issue-85765.rs:26:5
3030
|
3131
LL | let y: &usize = &mut(0);
32-
| - help: consider changing this to be a mutable reference: `&mut usize`
32+
| - consider changing this binding's type to be: `&mut usize`
3333
LL |
3434
LL | *y = 1;
3535
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ impl TestClient {
99
fn main() {
1010
let client = TestClient;
1111
let inner = client.get_inner_ref();
12-
//~^ HELP consider changing this to be a mutable reference
12+
//~^ NOTE consider changing this binding's type to be
1313
inner.clear();
1414
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
15+
//~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
1516
}

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

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

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

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

src/test/ui/borrowck/suggest-as-ref-on-mut-closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// This is not exactly right, yet.
22

33
// Ideally we should be suggesting `as_mut` for the first case,
4-
//and suggesting to change `as_ref` to `as_mut` in the second.
4+
// and suggesting to change `as_ref` to `as_mut` in the second.
55

66
fn x(cb: &mut Option<&mut dyn FnMut()>) {
77
cb.map(|cb| cb());

src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
2323
LL | cb.as_ref().map(|cb| cb());
2424
| -- ^^ `cb` is a `&` reference, so the data it refers to cannot be borrowed as mutable
2525
| |
26-
| help: consider changing this to be a mutable reference: `&mut &mut dyn FnMut()`
26+
| consider changing this binding's type to be: `&mut &mut dyn FnMut()`
2727

2828
error: aborting due to 2 previous errors
2929

src/test/ui/issues/issue-51515.rs

-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ fn main() {
55
*foo = 32;
66
//~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
77
let bar = foo;
8-
//~^ HELP consider changing this to be a mutable reference
9-
//~| SUGGESTION &mut i32
108
*bar = 64;
119
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
1210
}

src/test/ui/issues/issue-51515.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ LL | *foo = 32;
88
| ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
99

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

0 commit comments

Comments
 (0)