Skip to content

Commit 1dda298

Browse files
committed
Auto merge of rust-lang#104809 - matthiaskrgr:rollup-8abjdwh, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang#103908 (Suggest `.clone()` or `ref binding` on E0382) - rust-lang#104517 (Throw error on failure in loading llvm-plugin) - rust-lang#104594 (Properly handle `Pin<&mut dyn* Trait>` receiver in codegen) - rust-lang#104742 (Make `deref_into_dyn_supertrait` lint the impl and not the usage) - rust-lang#104753 (Pass `InferCtxt` to `DropRangeVisitor` so we can resolve vars) - rust-lang#104771 (Add regression test for issue rust-lang#99938) - rust-lang#104772 (Small accessibility improvements) - rust-lang#104775 (Use ObligationCtxt::normalize) - rust-lang#104778 (:arrow_up: rust-analyzer) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 341d8b8 + 1afbd6e commit 1dda298

File tree

253 files changed

+4084
-1171
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

253 files changed

+4084
-1171
lines changed

compiler/rustc_ast/src/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,7 @@ pub enum ExprKind {
13761376
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
13771377
///
13781378
/// `'label: loop { block }`
1379-
Loop(P<Block>, Option<Label>),
1379+
Loop(P<Block>, Option<Label>, Span),
13801380
/// A `match` block.
13811381
Match(P<Expr>, Vec<Arm>),
13821382
/// A closure (e.g., `move |a, b, c| a + b + c`).

compiler/rustc_ast/src/mut_visit.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1355,9 +1355,10 @@ pub fn noop_visit_expr<T: MutVisitor>(
13551355
vis.visit_block(body);
13561356
visit_opt(label, |label| vis.visit_label(label));
13571357
}
1358-
ExprKind::Loop(body, label) => {
1358+
ExprKind::Loop(body, label, span) => {
13591359
vis.visit_block(body);
13601360
visit_opt(label, |label| vis.visit_label(label));
1361+
vis.visit_span(span);
13611362
}
13621363
ExprKind::Match(expr, arms) => {
13631364
vis.visit_expr(expr);

compiler/rustc_ast/src/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
824824
visitor.visit_expr(subexpression);
825825
visitor.visit_block(block);
826826
}
827-
ExprKind::Loop(block, opt_label) => {
827+
ExprKind::Loop(block, opt_label, _) => {
828828
walk_list!(visitor, visit_label, opt_label);
829829
visitor.visit_block(block);
830830
}

compiler/rustc_ast_lowering/src/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
131131
let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
132132
this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label)
133133
}),
134-
ExprKind::Loop(body, opt_label) => self.with_loop_scope(e.id, |this| {
134+
ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| {
135135
hir::ExprKind::Loop(
136136
this.lower_block(body, false),
137137
this.lower_label(*opt_label),
138138
hir::LoopSource::Loop,
139-
DUMMY_SP,
139+
this.lower_span(*span),
140140
)
141141
}),
142142
ExprKind::TryBlock(body) => self.lower_expr_try_block(body),

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ impl<'a> State<'a> {
377377
self.space();
378378
self.print_block_with_attrs(blk, attrs);
379379
}
380-
ast::ExprKind::Loop(ref blk, opt_label) => {
380+
ast::ExprKind::Loop(ref blk, opt_label, _) => {
381381
if let Some(label) = opt_label {
382382
self.print_ident(label.ident);
383383
self.word_space(":");

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+194-30
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
167167
);
168168
}
169169

170-
self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
170+
let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
171171

172172
let mut is_loop_move = false;
173173
let mut in_pattern = false;
174+
let mut seen_spans = FxHashSet::default();
174175

175176
for move_site in &move_site_vec {
176177
let move_out = self.move_data.moves[(*move_site).moi];
@@ -191,37 +192,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
191192
is_loop_move = true;
192193
}
193194

194-
self.explain_captures(
195-
&mut err,
196-
span,
197-
move_span,
198-
move_spans,
199-
*moved_place,
200-
partially_str,
201-
loop_message,
202-
move_msg,
203-
is_loop_move,
204-
maybe_reinitialized_locations.is_empty(),
205-
);
206-
207-
if let (UseSpans::PatUse(span), []) =
208-
(move_spans, &maybe_reinitialized_locations[..])
209-
{
210-
if maybe_reinitialized_locations.is_empty() {
211-
err.span_suggestion_verbose(
212-
span.shrink_to_lo(),
213-
&format!(
214-
"borrow this field in the pattern to avoid moving {}",
215-
self.describe_place(moved_place.as_ref())
216-
.map(|n| format!("`{}`", n))
217-
.unwrap_or_else(|| "the value".to_string())
218-
),
219-
"ref ",
220-
Applicability::MachineApplicable,
221-
);
222-
in_pattern = true;
195+
if !seen_spans.contains(&move_span) {
196+
if !closure {
197+
self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern);
223198
}
199+
200+
self.explain_captures(
201+
&mut err,
202+
span,
203+
move_span,
204+
move_spans,
205+
*moved_place,
206+
partially_str,
207+
loop_message,
208+
move_msg,
209+
is_loop_move,
210+
maybe_reinitialized_locations.is_empty(),
211+
);
224212
}
213+
seen_spans.insert(move_span);
225214
}
226215

227216
use_spans.var_path_only_subdiag(&mut err, desired_action);
@@ -317,6 +306,160 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
317306
}
318307
}
319308

309+
fn suggest_ref_or_clone(
310+
&mut self,
311+
mpi: MovePathIndex,
312+
move_span: Span,
313+
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
314+
in_pattern: &mut bool,
315+
) {
316+
struct ExpressionFinder<'hir> {
317+
expr_span: Span,
318+
expr: Option<&'hir hir::Expr<'hir>>,
319+
pat: Option<&'hir hir::Pat<'hir>>,
320+
parent_pat: Option<&'hir hir::Pat<'hir>>,
321+
}
322+
impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
323+
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
324+
if e.span == self.expr_span {
325+
self.expr = Some(e);
326+
}
327+
hir::intravisit::walk_expr(self, e);
328+
}
329+
fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
330+
if p.span == self.expr_span {
331+
self.pat = Some(p);
332+
}
333+
if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, i, sub) = p.kind {
334+
if i.span == self.expr_span || p.span == self.expr_span {
335+
self.pat = Some(p);
336+
}
337+
// Check if we are in a situation of `ident @ ident` where we want to suggest
338+
// `ref ident @ ref ident` or `ref ident @ Struct { ref ident }`.
339+
if let Some(subpat) = sub && self.pat.is_none() {
340+
self.visit_pat(subpat);
341+
if self.pat.is_some() {
342+
self.parent_pat = Some(p);
343+
}
344+
return;
345+
}
346+
}
347+
hir::intravisit::walk_pat(self, p);
348+
}
349+
}
350+
let hir = self.infcx.tcx.hir();
351+
if let Some(hir::Node::Item(hir::Item {
352+
kind: hir::ItemKind::Fn(_, _, body_id),
353+
..
354+
})) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id()))
355+
&& let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
356+
{
357+
let place = &self.move_data.move_paths[mpi].place;
358+
let span = place.as_local()
359+
.map(|local| self.body.local_decls[local].source_info.span);
360+
let mut finder = ExpressionFinder {
361+
expr_span: move_span,
362+
expr: None,
363+
pat: None,
364+
parent_pat: None,
365+
};
366+
finder.visit_expr(expr);
367+
if let Some(span) = span && let Some(expr) = finder.expr {
368+
for (_, expr) in hir.parent_iter(expr.hir_id) {
369+
if let hir::Node::Expr(expr) = expr {
370+
if expr.span.contains(span) {
371+
// If the let binding occurs within the same loop, then that
372+
// loop isn't relevant, like in the following, the outermost `loop`
373+
// doesn't play into `x` being moved.
374+
// ```
375+
// loop {
376+
// let x = String::new();
377+
// loop {
378+
// foo(x);
379+
// }
380+
// }
381+
// ```
382+
break;
383+
}
384+
if let hir::ExprKind::Loop(.., loop_span) = expr.kind {
385+
err.span_label(loop_span, "inside of this loop");
386+
}
387+
}
388+
}
389+
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
390+
let hir_id = hir.get_parent_node(expr.hir_id);
391+
if let Some(parent) = hir.find(hir_id) {
392+
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
393+
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
394+
&& let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
395+
{
396+
(def_id.as_local(), args, 1)
397+
} else if let hir::Node::Expr(parent_expr) = parent
398+
&& let hir::ExprKind::Call(call, args) = parent_expr.kind
399+
&& let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
400+
{
401+
(def_id.as_local(), args, 0)
402+
} else {
403+
(None, &[][..], 0)
404+
};
405+
if let Some(def_id) = def_id
406+
&& let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id))
407+
&& let Some(fn_sig) = node.fn_sig()
408+
&& let Some(ident) = node.ident()
409+
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
410+
&& let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
411+
{
412+
let mut span: MultiSpan = arg.span.into();
413+
span.push_span_label(
414+
arg.span,
415+
"this parameter takes ownership of the value".to_string(),
416+
);
417+
let descr = match node.fn_kind() {
418+
Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
419+
Some(hir::intravisit::FnKind::Method(..)) => "method",
420+
Some(hir::intravisit::FnKind::Closure) => "closure",
421+
};
422+
span.push_span_label(
423+
ident.span,
424+
format!("in this {descr}"),
425+
);
426+
err.span_note(
427+
span,
428+
format!(
429+
"consider changing this parameter type in {descr} `{ident}` to \
430+
borrow instead if owning the value isn't necessary",
431+
),
432+
);
433+
}
434+
let place = &self.move_data.move_paths[mpi].place;
435+
let ty = place.ty(self.body, self.infcx.tcx).ty;
436+
if let hir::Node::Expr(parent_expr) = parent
437+
&& let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
438+
&& let hir::ExprKind::Path(
439+
hir::QPath::LangItem(LangItem::IntoIterIntoIter, _, _)
440+
) = call_expr.kind
441+
{
442+
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
443+
} else {
444+
self.suggest_cloning(err, ty, move_span);
445+
}
446+
}
447+
}
448+
if let Some(pat) = finder.pat {
449+
*in_pattern = true;
450+
let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())];
451+
if let Some(pat) = finder.parent_pat {
452+
sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string()));
453+
}
454+
err.multipart_suggestion_verbose(
455+
"borrow this binding in the pattern to avoid moving the value",
456+
sugg,
457+
Applicability::MachineApplicable,
458+
);
459+
}
460+
}
461+
}
462+
320463
fn report_use_of_uninitialized(
321464
&self,
322465
mpi: MovePathIndex,
@@ -590,6 +733,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
590733
true
591734
}
592735

736+
fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
737+
let tcx = self.infcx.tcx;
738+
// Try to find predicates on *generic params* that would allow copying `ty`
739+
let infcx = tcx.infer_ctxt().build();
740+
if infcx
741+
.type_implements_trait(
742+
tcx.lang_items().clone_trait().unwrap(),
743+
[tcx.erase_regions(ty)],
744+
self.param_env,
745+
)
746+
.must_apply_modulo_regions()
747+
{
748+
err.span_suggestion_verbose(
749+
span.shrink_to_hi(),
750+
"consider cloning the value if the performance cost is acceptable",
751+
".clone()".to_string(),
752+
Applicability::MachineApplicable,
753+
);
754+
}
755+
}
756+
593757
fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
594758
let tcx = self.infcx.tcx;
595759
let generics = tcx.generics_of(self.mir_def_id());

compiler/rustc_borrowck/src/diagnostics/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
7070
location: Location,
7171
place: PlaceRef<'tcx>,
7272
diag: &mut Diagnostic,
73-
) {
73+
) -> bool {
7474
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
7575
let mut target = place.local_or_deref_local();
7676
for stmt in &self.body[location.block].statements[location.statement_index..] {
@@ -106,7 +106,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
106106
{
107107
place.local_or_deref_local().unwrap()
108108
}
109-
_ => return,
109+
_ => return false,
110110
};
111111

112112
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
@@ -125,7 +125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
125125
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
126126
),
127127
);
128-
return;
128+
return true;
129129
}
130130
}
131131
}
@@ -149,9 +149,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
149149
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
150150
),
151151
);
152+
return true;
152153
}
153154
}
154155
}
156+
false
155157
}
156158

157159
/// End-user visible description of `place` if one can be found.

compiler/rustc_builtin_macros/src/assert/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
307307
| ExprKind::InlineAsm(_)
308308
| ExprKind::Let(_, _, _)
309309
| ExprKind::Lit(_)
310-
| ExprKind::Loop(_, _)
310+
| ExprKind::Loop(_, _, _)
311311
| ExprKind::MacCall(_)
312312
| ExprKind::Match(_, _)
313313
| ExprKind::Path(_, _)

0 commit comments

Comments
 (0)