1
Fork 0

try to suggest eliding redundant binding modifiers

This commit is contained in:
dianne 2025-02-05 04:05:01 -08:00
parent 060cc37f32
commit b32a5331dc
7 changed files with 81 additions and 48 deletions

View file

@ -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);
}
}

View file

@ -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 {