lower implicit deref patterns to THIR
Since this uses `pat_adjustments`, I've also tweaked the documentation to mention implicit deref patterns and made sure the pattern migration diagnostic logic accounts for it. I'll adjust `ExprUseVisitor` in a later commit and add some tests there for closure capture inference.
This commit is contained in:
parent
f35eae780b
commit
cb6c499bc9
3 changed files with 36 additions and 21 deletions
|
@ -4,7 +4,6 @@ use rustc_data_structures::fx::FxIndexMap;
|
|||
use rustc_errors::MultiSpan;
|
||||
use rustc_hir::{BindingMode, ByRef, HirId, Mutability};
|
||||
use rustc_lint as lint;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt};
|
||||
use rustc_span::{Ident, Span};
|
||||
|
||||
|
@ -87,19 +86,18 @@ impl<'a> PatMigration<'a> {
|
|||
}
|
||||
|
||||
/// Tracks when we're lowering a pattern that implicitly dereferences the scrutinee.
|
||||
/// This should only be called when the pattern type adjustments list `adjustments` is
|
||||
/// non-empty. Returns the prior default binding mode; this should be followed by a call to
|
||||
/// [`PatMigration::leave_ref`] to restore it when we leave the pattern.
|
||||
/// This should only be called when the pattern type adjustments list `adjustments` contains an
|
||||
/// implicit deref of a reference type. Returns the prior default binding mode; this should be
|
||||
/// followed by a call to [`PatMigration::leave_ref`] to restore it when we leave the pattern.
|
||||
pub(super) fn visit_implicit_derefs<'tcx>(
|
||||
&mut self,
|
||||
pat_span: Span,
|
||||
adjustments: &[ty::adjustment::PatAdjustment<'tcx>],
|
||||
) -> Option<(Span, Mutability)> {
|
||||
let implicit_deref_mutbls = adjustments.iter().map(|adjust| {
|
||||
let &ty::Ref(_, _, mutbl) = adjust.source.kind() else {
|
||||
span_bug!(pat_span, "pattern implicitly dereferences a non-ref type");
|
||||
};
|
||||
mutbl
|
||||
// Implicitly dereferencing references changes the default binding mode, but implicit derefs
|
||||
// of smart pointers do not. Thus, we only consider implicit derefs of reference types.
|
||||
let implicit_deref_mutbls = adjustments.iter().filter_map(|adjust| {
|
||||
if let &ty::Ref(_, _, mutbl) = adjust.source.kind() { Some(mutbl) } else { None }
|
||||
});
|
||||
|
||||
if !self.info.suggest_eliding_modes {
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::LitToConstInput;
|
|||
use rustc_middle::thir::{
|
||||
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
|
||||
};
|
||||
use rustc_middle::ty::adjustment::PatAdjustment;
|
||||
use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
|
@ -68,9 +68,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
|
||||
|
||||
// Track the default binding mode for the Rust 2024 migration suggestion.
|
||||
// Implicitly dereferencing references changes the default binding mode, but implicit deref
|
||||
// patterns do not. Only track binding mode changes if a ref type is in the adjustments.
|
||||
let mut opt_old_mode_span = None;
|
||||
if let Some(s) = &mut self.rust_2024_migration
|
||||
&& !adjustments.is_empty()
|
||||
&& adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
|
||||
{
|
||||
opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
|
||||
}
|
||||
|
@ -104,16 +106,22 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
|
||||
debug!("{:?}: wrapping pattern with type {:?}", thir_pat, adjust);
|
||||
Box::new(Pat {
|
||||
span: thir_pat.span,
|
||||
ty: adjust.source,
|
||||
kind: PatKind::Deref { subpattern: thir_pat },
|
||||
})
|
||||
debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
|
||||
let span = thir_pat.span;
|
||||
let kind = match adjust.kind {
|
||||
PatAdjust::BuiltinDeref => PatKind::Deref { subpattern: thir_pat },
|
||||
PatAdjust::OverloadedDeref => {
|
||||
let mutable = self.typeck_results.pat_has_ref_mut_binding(pat);
|
||||
let mutability =
|
||||
if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
|
||||
PatKind::DerefPattern { subpattern: thir_pat, mutability }
|
||||
}
|
||||
};
|
||||
Box::new(Pat { span, ty: adjust.source, kind })
|
||||
});
|
||||
|
||||
if let Some(s) = &mut self.rust_2024_migration
|
||||
&& !adjustments.is_empty()
|
||||
&& adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
|
||||
{
|
||||
s.leave_ref(opt_old_mode_span);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue