Skip to content

Commit a9b02e1

Browse files
drive-by: move Copy bound suggestion to its own function
1 parent 0f3c293 commit a9b02e1

File tree

1 file changed

+65
-60
lines changed

1 file changed

+65
-60
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+65-60
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
151151
.args_or_use()
152152
})
153153
.collect::<Vec<Span>>();
154+
154155
let reinits = maybe_reinitialized_locations.len();
155156
if reinits == 1 {
156157
err.span_label(reinit_spans[0], "this reinitialization might get skipped");
@@ -282,69 +283,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
282283
Some(ref name) => format!("`{}`", name),
283284
None => "value".to_owned(),
284285
};
285-
286-
let tcx = self.infcx.tcx;
287-
let generics = tcx.generics_of(self.mir_def_id());
288-
289286
if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, &note_msg) {
290287
// Suppress the next note, since we don't want to put more `Fn`-like bounds onto something that already has them
291288
} else if needs_note {
292-
if let Some(hir_generics) = tcx
293-
.typeck_root_def_id(self.mir_def_id().to_def_id())
294-
.as_local()
295-
.and_then(|def_id| tcx.hir().get_generics(def_id))
296-
{
297-
// Try to find predicates on *generic params* that would allow copying `ty`
298-
let predicates: Result<Vec<_>, _> = tcx.infer_ctxt().enter(|infcx| {
299-
let mut fulfill_cx =
300-
<dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
301-
302-
let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
303-
let cause = ObligationCause::new(
304-
span,
305-
self.mir_hir_id(),
306-
rustc_infer::traits::ObligationCauseCode::MiscObligation,
307-
);
308-
fulfill_cx.register_bound(
309-
&infcx,
310-
self.param_env,
311-
// Erase any region vids from the type, which may not be resolved
312-
infcx.tcx.erase_regions(ty),
313-
copy_did,
314-
cause,
315-
);
316-
// Select all, including ambiguous predicates
317-
let errors = fulfill_cx.select_all_or_error(&infcx);
318-
319-
// Only emit suggestion if all required predicates are on generic
320-
errors
321-
.into_iter()
322-
.map(|err| match err.obligation.predicate.kind().skip_binder() {
323-
PredicateKind::Trait(predicate) => {
324-
match predicate.self_ty().kind() {
325-
ty::Param(param_ty) => Ok((
326-
generics.type_param(param_ty, tcx),
327-
predicate.trait_ref.print_only_trait_path().to_string(),
328-
)),
329-
_ => Err(()),
330-
}
331-
}
332-
_ => Err(()),
333-
})
334-
.collect()
335-
});
336-
337-
if let Ok(predicates) = predicates {
338-
suggest_constraining_type_params(
339-
tcx,
340-
hir_generics,
341-
&mut err,
342-
predicates.iter().map(|(param, constraint)| {
343-
(param.name.as_str(), &**constraint, None)
344-
}),
345-
);
346-
}
347-
}
289+
self.suggest_adding_copy_bounds(&mut err, ty, span);
348290

349291
let span = if let Some(local) = place.as_local() {
350292
Some(self.body.local_decls[local].source_info.span)
@@ -450,6 +392,69 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
450392
true
451393
}
452394

395+
fn suggest_adding_copy_bounds(
396+
&self,
397+
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
398+
ty: Ty<'tcx>,
399+
span: Span,
400+
) {
401+
let tcx = self.infcx.tcx;
402+
let generics = tcx.generics_of(self.mir_def_id());
403+
404+
let Some(hir_generics) = tcx
405+
.typeck_root_def_id(self.mir_def_id().to_def_id())
406+
.as_local()
407+
.and_then(|def_id| tcx.hir().get_generics(def_id))
408+
else { return; };
409+
// Try to find predicates on *generic params* that would allow copying `ty`
410+
let predicates: Result<Vec<_>, _> = tcx.infer_ctxt().enter(|infcx| {
411+
let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
412+
413+
let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
414+
let cause = ObligationCause::new(
415+
span,
416+
self.mir_hir_id(),
417+
rustc_infer::traits::ObligationCauseCode::MiscObligation,
418+
);
419+
fulfill_cx.register_bound(
420+
&infcx,
421+
self.param_env,
422+
// Erase any region vids from the type, which may not be resolved
423+
infcx.tcx.erase_regions(ty),
424+
copy_did,
425+
cause,
426+
);
427+
// Select all, including ambiguous predicates
428+
let errors = fulfill_cx.select_all_or_error(&infcx);
429+
430+
// Only emit suggestion if all required predicates are on generic
431+
errors
432+
.into_iter()
433+
.map(|err| match err.obligation.predicate.kind().skip_binder() {
434+
PredicateKind::Trait(predicate) => match predicate.self_ty().kind() {
435+
ty::Param(param_ty) => Ok((
436+
generics.type_param(param_ty, tcx),
437+
predicate.trait_ref.print_only_trait_path().to_string(),
438+
)),
439+
_ => Err(()),
440+
},
441+
_ => Err(()),
442+
})
443+
.collect()
444+
});
445+
446+
if let Ok(predicates) = predicates {
447+
suggest_constraining_type_params(
448+
tcx,
449+
hir_generics,
450+
err,
451+
predicates
452+
.iter()
453+
.map(|(param, constraint)| (param.name.as_str(), &**constraint, None)),
454+
);
455+
}
456+
}
457+
453458
pub(crate) fn report_move_out_while_borrowed(
454459
&mut self,
455460
location: Location,

0 commit comments

Comments
 (0)