Suggest turning APITs into generics in opaque overcaptures
This commit is contained in:
parent
b73478b6ee
commit
ad20906065
7 changed files with 202 additions and 41 deletions
|
@ -3,7 +3,7 @@ use std::cell::LazyCell;
|
|||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::{Applicability, LintDiagnostic};
|
||||
use rustc_errors::{LintDiagnostic, Subdiagnostic};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
|
@ -22,6 +22,7 @@ use rustc_session::lint::FutureIncompatibilityReason;
|
|||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_trait_selection::errors::{impl_trait_overcapture_suggestion, AddPreciseCapturingForOvercapture};
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
|
||||
|
||||
|
@ -334,32 +335,12 @@ where
|
|||
// If we have uncaptured args, and if the opaque doesn't already have
|
||||
// `use<>` syntax on it, and we're < edition 2024, then warn the user.
|
||||
if !uncaptured_args.is_empty() {
|
||||
let suggestion = if let Ok(snippet) =
|
||||
self.tcx.sess.source_map().span_to_snippet(opaque_span)
|
||||
&& snippet.starts_with("impl ")
|
||||
{
|
||||
let (lifetimes, others): (Vec<_>, Vec<_>) =
|
||||
captured.into_iter().partition(|def_id| {
|
||||
self.tcx.def_kind(*def_id) == DefKind::LifetimeParam
|
||||
});
|
||||
// Take all lifetime params first, then all others (ty/ct).
|
||||
let generics: Vec<_> = lifetimes
|
||||
.into_iter()
|
||||
.chain(others)
|
||||
.map(|def_id| self.tcx.item_name(def_id).to_string())
|
||||
.collect();
|
||||
// Make sure that we're not trying to name any APITs
|
||||
if generics.iter().all(|name| !name.starts_with("impl ")) {
|
||||
Some((
|
||||
format!(" + use<{}>", generics.join(", ")),
|
||||
opaque_span.shrink_to_hi(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let suggestion = impl_trait_overcapture_suggestion(
|
||||
self.tcx,
|
||||
opaque_def_id,
|
||||
self.parent_def_id,
|
||||
captured,
|
||||
);
|
||||
|
||||
let uncaptured_spans: Vec<_> = uncaptured_args
|
||||
.into_iter()
|
||||
|
@ -451,7 +432,7 @@ struct ImplTraitOvercapturesLint<'tcx> {
|
|||
uncaptured_spans: Vec<Span>,
|
||||
self_ty: Ty<'tcx>,
|
||||
num_captured: usize,
|
||||
suggestion: Option<(String, Span)>,
|
||||
suggestion: Option<AddPreciseCapturingForOvercapture>,
|
||||
}
|
||||
|
||||
impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
|
||||
|
@ -461,13 +442,8 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
|
|||
.arg("num_captured", self.num_captured)
|
||||
.span_note(self.uncaptured_spans, fluent::lint_note)
|
||||
.note(fluent::lint_note2);
|
||||
if let Some((suggestion, span)) = self.suggestion {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
fluent::lint_suggestion,
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if let Some(suggestion) = self.suggestion {
|
||||
suggestion.add_to_diag(diag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue