Skip to content

Commit f35eae7

Browse files
committed
store the kind of pattern adjustments in pat_adjustments
This allows us to better distinguish builtin and overloaded implicit dereferences.
1 parent 0fe8f34 commit f35eae7

File tree

8 files changed

+50
-16
lines changed

8 files changed

+50
-16
lines changed

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,9 +1227,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
12271227
// actually this is somewhat "disjoint" from the code below
12281228
// that aims to account for `ref x`.
12291229
if let Some(vec) = self.cx.typeck_results().pat_adjustments().get(pat.hir_id) {
1230-
if let Some(first_ty) = vec.first() {
1231-
debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
1232-
return Ok(*first_ty);
1230+
if let Some(first_adjust) = vec.first() {
1231+
debug!("pat_ty(pat={:?}) found adjustment `{:?}`", pat, first_adjust);
1232+
return Ok(first_adjust.source);
12331233
}
12341234
} else if let PatKind::Ref(subpat, _) = pat.kind
12351235
&& self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id)

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_trait_selection::infer::InferCtxtExt;
2929
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
3030
use tracing::{debug, instrument, trace};
3131
use ty::VariantDef;
32+
use ty::adjustment::{PatAdjust, PatAdjustment};
3233

3334
use super::report_unexpected_variant_res;
3435
use crate::expectation::Expectation;
@@ -415,7 +416,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
415416
.pat_adjustments_mut()
416417
.entry(pat.hir_id)
417418
.or_default()
418-
.push(expected);
419+
.push(PatAdjustment { kind: PatAdjust::BuiltinDeref, source: expected });
419420

420421
let mut binding_mode = ByRef::Yes(match pat_info.binding_mode {
421422
// If default binding mode is by value, make it `ref` or `ref mut`

compiler/rustc_middle/src/ty/adjustment.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,25 @@ pub enum CustomCoerceUnsized {
214214
/// Records the index of the field being coerced.
215215
Struct(FieldIdx),
216216
}
217+
218+
/// Represents an implicit coercion applied to the scrutinee of a match before testing a pattern
219+
/// against it. Currently, this is used only for implicit dereferences.
220+
#[derive(Clone, Copy, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
221+
pub struct PatAdjustment<'tcx> {
222+
pub kind: PatAdjust,
223+
/// The type of the scrutinee before the adjustment is applied, or the "adjusted type" of the
224+
/// pattern.
225+
pub source: Ty<'tcx>,
226+
}
227+
228+
/// Represents implicit coercions of patterns' types, rather than values' types.
229+
#[derive(Clone, Copy, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
230+
#[derive(TypeFoldable, TypeVisitable)]
231+
pub enum PatAdjust {
232+
/// An implicit dereference before matching, such as when matching the pattern `0` against a
233+
/// scrutinee of type `&u8` or `&mut u8`.
234+
BuiltinDeref,
235+
/// An implicit call to `Deref(Mut)::deref(_mut)` before matching, such as when matching the
236+
/// pattern `[..]` against a scrutinee of type `Vec<T>`.
237+
OverloadedDeref,
238+
}

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
6161
}
6262
}
6363

64+
impl<'tcx> fmt::Debug for ty::adjustment::PatAdjustment<'tcx> {
65+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66+
write!(f, "{} -> {:?}", self.source, self.kind)
67+
}
68+
}
69+
6470
impl fmt::Debug for ty::BoundRegionKind {
6571
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6672
match *self {

compiler/rustc_middle/src/ty/typeck_results.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub struct TypeckResults<'tcx> {
9090
///
9191
/// See:
9292
/// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
93-
pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
93+
pat_adjustments: ItemLocalMap<Vec<ty::adjustment::PatAdjustment<'tcx>>>,
9494

9595
/// Set of reference patterns that match against a match-ergonomics inserted reference
9696
/// (as opposed to against a reference in the scrutinee type).
@@ -403,11 +403,15 @@ impl<'tcx> TypeckResults<'tcx> {
403403
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
404404
}
405405

406-
pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
406+
pub fn pat_adjustments(
407+
&self,
408+
) -> LocalTableInContext<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
407409
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
408410
}
409411

410-
pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
412+
pub fn pat_adjustments_mut(
413+
&mut self,
414+
) -> LocalTableInContextMut<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
411415
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
412416
}
413417

compiler/rustc_mir_build/src/thir/pattern/migration.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_errors::MultiSpan;
55
use rustc_hir::{BindingMode, ByRef, HirId, Mutability};
66
use rustc_lint as lint;
77
use rustc_middle::span_bug;
8-
use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, Ty, TyCtxt};
8+
use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt};
99
use rustc_span::{Ident, Span};
1010

1111
use crate::errors::{Rust2024IncompatiblePat, Rust2024IncompatiblePatSugg};
@@ -93,10 +93,10 @@ impl<'a> PatMigration<'a> {
9393
pub(super) fn visit_implicit_derefs<'tcx>(
9494
&mut self,
9595
pat_span: Span,
96-
adjustments: &[Ty<'tcx>],
96+
adjustments: &[ty::adjustment::PatAdjustment<'tcx>],
9797
) -> Option<(Span, Mutability)> {
98-
let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| {
99-
let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
98+
let implicit_deref_mutbls = adjustments.iter().map(|adjust| {
99+
let &ty::Ref(_, _, mutbl) = adjust.source.kind() else {
100100
span_bug!(pat_span, "pattern implicitly dereferences a non-ref type");
101101
};
102102
mutbl

compiler/rustc_mir_build/src/thir/pattern/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_middle::mir::interpret::LitToConstInput;
1818
use rustc_middle::thir::{
1919
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
2020
};
21+
use rustc_middle::ty::adjustment::PatAdjustment;
2122
use rustc_middle::ty::layout::IntegerExt;
2223
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode};
2324
use rustc_middle::{bug, span_bug};
@@ -63,7 +64,7 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
6364

6465
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
6566
fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
66-
let adjustments: &[Ty<'tcx>] =
67+
let adjustments: &[PatAdjustment<'tcx>] =
6768
self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
6869

6970
// Track the default binding mode for the Rust 2024 migration suggestion.
@@ -102,11 +103,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
102103
_ => self.lower_pattern_unadjusted(pat),
103104
};
104105

105-
let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| {
106-
debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty);
106+
let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
107+
debug!("{:?}: wrapping pattern with type {:?}", thir_pat, adjust);
107108
Box::new(Pat {
108109
span: thir_pat.span,
109-
ty: *ref_ty,
110+
ty: adjust.source,
110111
kind: PatKind::Deref { subpattern: thir_pat },
111112
})
112113
});

src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ fn find_first_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(Span, Mut
179179
};
180180
if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id) {
181181
if let [first, ..] = **adjustments {
182-
if let ty::Ref(.., mutability) = *first.kind() {
182+
if let ty::Ref(.., mutability) = *first.source.kind() {
183183
let level = if p.hir_id == pat.hir_id {
184184
Level::Top
185185
} else {

0 commit comments

Comments
 (0)