Skip to content

Commit 4c7213c

Browse files
committed
review comments
Added comments and reworded messages
1 parent dea9b50 commit 4c7213c

File tree

4 files changed

+48
-20
lines changed

4 files changed

+48
-20
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10061006
can_suggest_clone
10071007
}
10081008

1009-
fn suggest_cloning_on_spread_operator(
1009+
/// We have `S { foo: val, ..base }`, and we suggest instead writing
1010+
/// `S { foo: val, bar: base.bar.clone(), .. }` when valid.
1011+
fn suggest_cloning_on_functional_record_update(
10101012
&self,
10111013
err: &mut Diag<'_>,
10121014
ty: Ty<'tcx>,
@@ -1046,7 +1048,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10461048
for field in &variant.fields {
10471049
// In practice unless there are more than one field with the same type, we'll be
10481050
// suggesting a single field at a type, because we don't aggregate multiple borrow
1049-
// checker errors involving the spread operator into a single one.
1051+
// checker errors involving the functional record update sytnax into a single one.
10501052
let field_ty = field.ty(self.infcx.tcx, args);
10511053
let ident = field.ident(self.infcx.tcx);
10521054
if field_ty == ty && fields.iter().all(|field| field.ident.name != ident.name) {
@@ -1088,7 +1090,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10881090
String::new()
10891091
};
10901092
let msg = format!(
1091-
"{prefix}clone the value from the field instead of using the spread operator syntax",
1093+
"{prefix}clone the value from the field instead of using the functional record update \
1094+
syntax",
10921095
);
10931096
err.span_suggestion_verbose(span, msg, sugg, Applicability::MachineApplicable);
10941097
}
@@ -1105,7 +1108,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11051108
// `Location` that covers both the `S { ... }` literal, all of its fields and the
11061109
// `base`. If the move happens because of `S { foo: val, bar: base.bar }` the `expr`
11071110
// will already be correct. Instead, we see if we can suggest writing.
1108-
self.suggest_cloning_on_spread_operator(err, ty, expr);
1111+
self.suggest_cloning_on_functional_record_update(err, ty, expr);
11091112
return;
11101113
}
11111114

@@ -1225,6 +1228,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12251228
.must_apply_modulo_regions()
12261229
}
12271230

1231+
/// Given an expression, check if it is a method call `foo.clone()`, where `foo` and
1232+
/// `foo.clone()` both have the same type, returning the span for `.clone()` if so.
12281233
pub(crate) fn clone_on_reference(&self, expr: &hir::Expr<'_>) -> Option<Span> {
12291234
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
12301235
if let hir::ExprKind::MethodCall(segment, rcvr, args, span) = expr.kind
@@ -1276,6 +1281,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12761281
};
12771282
let mut sugg = Vec::with_capacity(2);
12781283
let mut inner_expr = expr;
1284+
// Remove uses of `&` and `*` when suggesting `.clone()`.
12791285
while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) =
12801286
&inner_expr.kind
12811287
{
@@ -1841,13 +1847,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
18411847
&self,
18421848
err: &mut Diag<'_>,
18431849
ty: Ty<'tcx>,
1844-
def_id: DefId,
1850+
trait_def_id: DefId,
18451851
span: Span,
18461852
) {
1847-
self.suggest_adding_bounds(err, ty, def_id, span);
1853+
self.suggest_adding_bounds(err, ty, trait_def_id, span);
18481854
if let ty::Adt(..) = ty.kind() {
1849-
// The type doesn't implement DefId.
1850-
let trait_ref = ty::Binder::dummy(ty::TraitRef::new(self.infcx.tcx, def_id, [ty]));
1855+
// The type doesn't implement the trait.
1856+
let trait_ref =
1857+
ty::Binder::dummy(ty::TraitRef::new(self.infcx.tcx, trait_def_id, [ty]));
18511858
let obligation = Obligation::new(
18521859
self.infcx.tcx,
18531860
ObligationCause::dummy(),

compiler/rustc_borrowck/src/diagnostics/mod.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10491049
is_loop_message,
10501050
},
10511051
);
1052+
// Check if the move occurs on a value because of a call on a closure that comes
1053+
// from a type parameter `F: FnOnce()`. If so, we provide a targeted `note`:
1054+
// ```
1055+
// error[E0382]: use of moved value: `blk`
1056+
// --> $DIR/once-cant-call-twice-on-heap.rs:8:5
1057+
// |
1058+
// LL | fn foo<F:FnOnce()>(blk: F) {
1059+
// | --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
1060+
// LL | blk();
1061+
// | ----- `blk` moved due to this call
1062+
// LL | blk();
1063+
// | ^^^ value used here after move
1064+
// |
1065+
// note: `FnOnce` closures can only be called once
1066+
// --> $DIR/once-cant-call-twice-on-heap.rs:6:10
1067+
// |
1068+
// LL | fn foo<F:FnOnce()>(blk: F) {
1069+
// | ^^^^^^^^ `F` is made to be an `FnOnce` closure here
1070+
// LL | blk();
1071+
// | ----- this value implements `FnOnce`, which causes it to be moved when called
1072+
// ```
10521073
if let ty::Param(param_ty) = self_ty.kind()
10531074
&& let generics = self.infcx.tcx.generics_of(self.mir_def_id())
10541075
&& let param = generics.type_param(param_ty, self.infcx.tcx)

tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ note: `B` doesn't implement `Copy` or `Clone`
1212
|
1313
LL | struct B;
1414
| ^^^^^^^^
15-
help: if `B` implemented `Clone`, you could clone the value from the field instead of using the spread operator syntax
15+
help: if `B` implemented `Clone`, you could clone the value from the field instead of using the functional record update syntax
1616
|
1717
LL | let _s2 = S { a: 2, b: s0.b.clone(), ..s0 };
1818
| +++++++++++++++++
@@ -31,7 +31,7 @@ note: `B` doesn't implement `Copy` or `Clone`
3131
|
3232
LL | struct B;
3333
| ^^^^^^^^
34-
help: if `B` implemented `Clone`, you could clone the value from the field instead of using the spread operator syntax
34+
help: if `B` implemented `Clone`, you could clone the value from the field instead of using the functional record update syntax
3535
|
3636
LL | let _s2 = S { a: 2, b: s0.b.clone(), c: s0.c.clone() };
3737
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -50,7 +50,7 @@ note: `B` doesn't implement `Copy` or `Clone`
5050
|
5151
LL | struct B;
5252
| ^^^^^^^^
53-
help: if `B` implemented `Clone`, you could clone the value from the field instead of using the spread operator syntax
53+
help: if `B` implemented `Clone`, you could clone the value from the field instead of using the functional record update syntax
5454
|
5555
LL | let _s2 = S { a: 2, b: s0.b.clone(), c: s0.c.clone() };
5656
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -69,7 +69,7 @@ note: `B` doesn't implement `Copy` or `Clone`
6969
|
7070
LL | struct B;
7171
| ^^^^^^^^
72-
help: if `B` implemented `Clone`, you could clone the value from the field instead of using the spread operator syntax
72+
help: if `B` implemented `Clone`, you could clone the value from the field instead of using the functional record update syntax
7373
|
7474
LL | let _s2 = S { a: 2, b: s0.b.clone(), ..s0 };
7575
| +++++++++++++++++
@@ -83,7 +83,7 @@ LL | let _s2 = S { a: 2, ..s0 };
8383
| cannot move out of here
8484
| move occurs because `s0.c` has type `K`, which does not implement the `Copy` trait
8585
|
86-
help: clone the value from the field instead of using the spread operator syntax
86+
help: clone the value from the field instead of using the functional record update syntax
8787
|
8888
LL | let _s2 = S { a: 2, c: s0.c.clone(), ..s0 };
8989
| +++++++++++++++++
@@ -97,7 +97,7 @@ LL | let _s2 = T { a: 2, ..s0 };
9797
| cannot move out of here
9898
| move occurs because `s0.b` has type `Box<isize>`, which does not implement the `Copy` trait
9999
|
100-
help: clone the value from the field instead of using the spread operator syntax
100+
help: clone the value from the field instead of using the functional record update syntax
101101
|
102102
LL | let _s2 = T { a: 2, b: s0.b.clone() };
103103
| ~~~~~~~~~~~~~~~~~
@@ -111,7 +111,7 @@ LL | let _s2 = T { ..s0 };
111111
| cannot move out of here
112112
| move occurs because `s0.b` has type `Box<isize>`, which does not implement the `Copy` trait
113113
|
114-
help: clone the value from the field instead of using the spread operator syntax
114+
help: clone the value from the field instead of using the functional record update syntax
115115
|
116116
LL | let _s2 = T { b: s0.b.clone(), ..s0 };
117117
| ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -139,7 +139,7 @@ LL | let _s2 = V { a: 2, ..s0 };
139139
| cannot move out of here
140140
| move occurs because `s0.b` has type `Box<isize>`, which does not implement the `Copy` trait
141141
|
142-
help: clone the value from the field instead of using the spread operator syntax
142+
help: clone the value from the field instead of using the functional record update syntax
143143
|
144144
LL | let _s2 = V { a: 2, b: s0.b.clone(), ..s0 };
145145
| +++++++++++++++++
@@ -153,7 +153,7 @@ LL | let _s2 = V { a: 2, ..s0 };
153153
| cannot move out of here
154154
| move occurs because `s0.c` has type `K`, which does not implement the `Copy` trait
155155
|
156-
help: clone the value from the field instead of using the spread operator syntax
156+
help: clone the value from the field instead of using the functional record update syntax
157157
|
158158
LL | let _s2 = V { a: 2, c: s0.c.clone(), ..s0 };
159159
| +++++++++++++++++
@@ -167,7 +167,7 @@ LL | let _s2 = V { a: 2, ..s0 };
167167
| cannot move out of here
168168
| move occurs because `s0.b` has type `Box<isize>`, which does not implement the `Copy` trait
169169
|
170-
help: clone the value from the field instead of using the spread operator syntax
170+
help: clone the value from the field instead of using the functional record update syntax
171171
|
172172
LL | let _s2 = V { a: 2, b: s0.b.clone(), ..s0 };
173173
| +++++++++++++++++
@@ -181,7 +181,7 @@ LL | let _s2 = V { a: 2, ..s0 };
181181
| cannot move out of here
182182
| move occurs because `s0.c` has type `Clonable`, which does not implement the `Copy` trait
183183
|
184-
help: clone the value from the field instead of using the spread operator syntax
184+
help: clone the value from the field instead of using the functional record update syntax
185185
|
186186
LL | let _s2 = V { a: 2, c: s0.c.clone(), ..s0 };
187187
| +++++++++++++++++

tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | let _b = A { y: Arc::new(3), ..a };
77
| cannot move out of here
88
| move occurs because `a.x` has type `Arc<isize>`, which does not implement the `Copy` trait
99
|
10-
help: clone the value from the field instead of using the spread operator syntax
10+
help: clone the value from the field instead of using the functional record update syntax
1111
|
1212
LL | let _b = A { y: Arc::new(3), x: a.x.clone() };
1313
| ~~~~~~~~~~~~~~~~

0 commit comments

Comments
 (0)