try to suggest eliding redundant binding modifiers
This commit is contained in:
parent
060cc37f32
commit
b32a5331dc
7 changed files with 81 additions and 48 deletions
|
@ -1107,6 +1107,9 @@ pub(crate) struct Rust2024IncompatiblePat {
|
|||
}
|
||||
|
||||
pub(crate) struct Rust2024IncompatiblePatSugg {
|
||||
/// If true, our suggestion is to elide explicit binding modifiers.
|
||||
/// If false, our suggestion is to make the pattern fully explicit.
|
||||
pub(crate) suggest_eliding_modes: bool,
|
||||
pub(crate) suggestion: Vec<(Span, String)>,
|
||||
pub(crate) ref_pattern_count: usize,
|
||||
pub(crate) binding_mode_count: usize,
|
||||
|
@ -1144,16 +1147,18 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg {
|
|||
} else {
|
||||
Applicability::MaybeIncorrect
|
||||
};
|
||||
let plural_derefs = pluralize!(self.ref_pattern_count);
|
||||
let and_modes = if self.binding_mode_count > 0 {
|
||||
format!(" and variable binding mode{}", pluralize!(self.binding_mode_count))
|
||||
let msg = if self.suggest_eliding_modes {
|
||||
let plural_modes = pluralize!(self.binding_mode_count);
|
||||
format!("remove the unnecessary binding modifier{plural_modes}")
|
||||
} else {
|
||||
String::new()
|
||||
let plural_derefs = pluralize!(self.ref_pattern_count);
|
||||
let and_modes = if self.binding_mode_count > 0 {
|
||||
format!(" and variable binding mode{}", pluralize!(self.binding_mode_count))
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
format!("make the implied reference pattern{plural_derefs}{and_modes} explicit")
|
||||
};
|
||||
diag.multipart_suggestion_verbose(
|
||||
format!("make the implied reference pattern{plural_derefs}{and_modes} explicit"),
|
||||
self.suggestion,
|
||||
applicability,
|
||||
);
|
||||
diag.multipart_suggestion_verbose(msg, self.suggestion, applicability);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,13 +49,16 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
|
|||
tcx,
|
||||
typing_env,
|
||||
typeck_results,
|
||||
rust_2024_migration_suggestion: migration_info.and(Some(Rust2024IncompatiblePatSugg {
|
||||
suggestion: Vec::new(),
|
||||
ref_pattern_count: 0,
|
||||
binding_mode_count: 0,
|
||||
default_mode_span: None,
|
||||
default_mode_labels: Default::default(),
|
||||
})),
|
||||
rust_2024_migration_suggestion: migration_info.and_then(|info| {
|
||||
Some(Rust2024IncompatiblePatSugg {
|
||||
suggest_eliding_modes: info.suggest_eliding_modes,
|
||||
suggestion: Vec::new(),
|
||||
ref_pattern_count: 0,
|
||||
binding_mode_count: 0,
|
||||
default_mode_span: None,
|
||||
default_mode_labels: Default::default(),
|
||||
})
|
||||
}),
|
||||
};
|
||||
let result = pcx.lower_pattern(pat);
|
||||
debug!("pat_from_hir({:?}) = {:?}", pat, result);
|
||||
|
@ -107,27 +110,22 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
if let Some(s) = &mut self.rust_2024_migration_suggestion
|
||||
&& !adjustments.is_empty()
|
||||
{
|
||||
let mut min_mutbl = Mutability::Mut;
|
||||
let suggestion_str: String = adjustments
|
||||
.iter()
|
||||
.map(|ref_ty| {
|
||||
let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
|
||||
span_bug!(pat.span, "pattern implicitly dereferences a non-ref type");
|
||||
};
|
||||
let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| {
|
||||
let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
|
||||
span_bug!(pat.span, "pattern implicitly dereferences a non-ref type");
|
||||
};
|
||||
mutbl
|
||||
});
|
||||
|
||||
match mutbl {
|
||||
Mutability::Not => {
|
||||
min_mutbl = Mutability::Not;
|
||||
"&"
|
||||
}
|
||||
Mutability::Mut => "&mut ",
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str));
|
||||
s.ref_pattern_count += adjustments.len();
|
||||
if !s.suggest_eliding_modes {
|
||||
let suggestion_str: String =
|
||||
implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect();
|
||||
s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str));
|
||||
s.ref_pattern_count += adjustments.len();
|
||||
}
|
||||
|
||||
// Remember if this changed the default binding mode, in case we want to label it.
|
||||
let min_mutbl = implicit_deref_mutbls.min().unwrap();
|
||||
if s.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) {
|
||||
opt_old_mode_span = Some(s.default_mode_span);
|
||||
s.default_mode_span = Some((pat.span, min_mutbl));
|
||||
|
@ -413,8 +411,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
{
|
||||
// If this overrides a by-ref default binding mode, label the binding mode.
|
||||
s.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
|
||||
// If our suggestion is to elide redundnt modes, this will be one of them.
|
||||
if s.suggest_eliding_modes {
|
||||
s.suggestion.push((pat.span.with_hi(ident.span.lo()), String::new()));
|
||||
s.binding_mode_count += 1;
|
||||
}
|
||||
}
|
||||
if explicit_ba.0 == ByRef::No
|
||||
if !s.suggest_eliding_modes
|
||||
&& explicit_ba.0 == ByRef::No
|
||||
&& let ByRef::Yes(mutbl) = mode.0
|
||||
{
|
||||
let sugg_str = match mutbl {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue