Skip to content

Commit 64c7917

Browse files
committed
store the kind of pattern adjustments in pat_adjustments
1 parent 2933772 commit 64c7917

File tree

8 files changed

+61
-38
lines changed

8 files changed

+61
-38
lines changed

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1228,9 +1228,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
12281228
// actually this is somewhat "disjoint" from the code below
12291229
// that aims to account for `ref x`.
12301230
if let Some(vec) = self.cx.typeck_results().pat_adjustments().get(pat.hir_id) {
1231-
if let Some(first_ty) = vec.first() {
1232-
debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
1233-
return Ok(*first_ty);
1231+
if let Some(first_adjust) = vec.first() {
1232+
debug!("pat_ty(pat={:?}) found adjustment `{:?}`", pat, first_adjust);
1233+
return Ok(first_adjust.source);
12341234
}
12351235
} else if let PatKind::Ref(subpat, _) = pat.kind
12361236
&& self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id)
@@ -1677,12 +1677,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16771677
// `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
16781678
// and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
16791679
let typeck_results = self.cx.typeck_results();
1680-
let adjustments: &[Ty<'tcx>] =
1680+
let adjustments: &[adjustment::PatAdjustment<'tcx>] =
16811681
typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
1682-
let mut ref_tys = adjustments.iter().peekable();
1683-
while let Some(ref_ty) = ref_tys.next() {
1682+
let mut adjusts = adjustments.iter().peekable();
1683+
while let Some(adjust) = adjusts.next() {
16841684
debug!("applying adjustment to place_with_id={:?}", place_with_id);
1685-
place_with_id = match ref_ty.pat_adjust_kind() {
1685+
place_with_id = match adjust.kind {
16861686
adjustment::PatAdjust::BuiltinDeref => self.cat_deref(pat.hir_id, place_with_id)?,
16871687
adjustment::PatAdjust::OverloadedDeref => {
16881688
// This adjustment corresponds to an overloaded deref; it borrows the scrutinee to
@@ -1691,8 +1691,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16911691
// HACK(dianne): giving the callback a fake deref pattern makes sure it behaves the
16921692
// same as it would if this were an explicit deref pattern.
16931693
op(&place_with_id, &hir::Pat { kind: PatKind::Deref(pat), ..*pat })?;
1694-
let target_ty = match ref_tys.peek() {
1695-
Some(&&target_ty) => target_ty,
1694+
let target_ty = match adjusts.peek() {
1695+
Some(&&next_adjust) => next_adjust.source,
16961696
// At the end of the deref chain, we get `pat`'s scrutinee.
16971697
None => self.pat_ty_unadjusted(pat)?,
16981698
};

compiler/rustc_hir_typeck/src/pat.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_trait_selection::infer::InferCtxtExt;
3030
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
3131
use tracing::{debug, instrument, trace};
3232
use ty::VariantDef;
33-
use ty::adjustment::PatAdjust;
33+
use ty::adjustment::{PatAdjust, PatAdjustment};
3434

3535
use super::report_unexpected_variant_res;
3636
use crate::expectation::Expectation;
@@ -486,12 +486,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
486486
// If we implicitly inserted overloaded dereferences before matching, check the pattern to
487487
// see if the dereferenced types need `DerefMut` bounds.
488488
if let Some(derefed_tys) = self.typeck_results.borrow().pat_adjustments().get(pat.hir_id)
489-
&& derefed_tys.iter().any(|ty| ty.pat_adjust_kind() == PatAdjust::OverloadedDeref)
489+
&& derefed_tys.iter().any(|adjust| adjust.kind == PatAdjust::OverloadedDeref)
490490
{
491491
self.register_deref_mut_bounds_if_needed(
492492
pat.span,
493493
pat,
494-
derefed_tys.iter().filter(|ty| !ty.is_ref()).copied(),
494+
derefed_tys.iter().filter_map(|adjust| match adjust.kind {
495+
PatAdjust::OverloadedDeref => Some(adjust.source),
496+
PatAdjust::BuiltinDeref => None,
497+
}),
495498
);
496499
}
497500

@@ -721,7 +724,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
721724
debug!("inspecting {:?}", expected);
722725
debug!("current discriminant can be dereferenced, inserting implicit deref");
723726
// Preserve the reference type. We'll need it later during THIR lowering.
724-
pat_adjustments.push(expected);
727+
pat_adjustments.push(PatAdjustment {
728+
source: expected,
729+
kind: if expected.is_ref() {
730+
PatAdjust::BuiltinDeref
731+
} else {
732+
PatAdjust::OverloadedDeref
733+
},
734+
});
725735

726736
expected = self.try_structurally_resolve_type(pat.span, inner_ty);
727737
}

compiler/rustc_middle/src/ty/adjustment.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,19 @@ pub enum CustomCoerceUnsized {
215215
Struct(FieldIdx),
216216
}
217217

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+
218228
/// Represents implicit coercions of patterns' types, rather than values' types.
219-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
229+
#[derive(Clone, Copy, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
230+
#[derive(TypeFoldable, TypeVisitable)]
220231
pub enum PatAdjust {
221232
/// An implicit dereference before matching, such as when matching the pattern `0` against a
222233
/// scrutinee of type `&u8` or `&mut u8`.
@@ -226,11 +237,3 @@ pub enum PatAdjust {
226237
/// pattern `[..]` against a scrutinee of type `Vec<T>`.
227238
OverloadedDeref,
228239
}
229-
230-
impl<'tcx> Ty<'tcx> {
231-
/// Given an adjusted pattern type (see [`ty::typeck_results::TypeckResults::pat_adjustments`]),
232-
/// determine what operation dereferences it, e.g. for building the pattern's THIR.
233-
pub fn pat_adjust_kind(self) -> PatAdjust {
234-
if self.is_ref() { PatAdjust::BuiltinDeref } else { PatAdjust::OverloadedDeref }
235-
}
236-
}

compiler/rustc_middle/src/ty/structural_impls.rs

+6
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

+7-3
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub struct TypeckResults<'tcx> {
9999
///
100100
/// See:
101101
/// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
102-
pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
102+
pat_adjustments: ItemLocalMap<Vec<ty::adjustment::PatAdjustment<'tcx>>>,
103103

104104
/// Set of reference patterns that match against a match-ergonomics inserted reference
105105
/// (as opposed to against a reference in the scrutinee type).
@@ -412,11 +412,15 @@ impl<'tcx> TypeckResults<'tcx> {
412412
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
413413
}
414414

415-
pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
415+
pub fn pat_adjustments(
416+
&self,
417+
) -> LocalTableInContext<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
416418
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
417419
}
418420

419-
pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
421+
pub fn pat_adjustments_mut(
422+
&mut self,
423+
) -> LocalTableInContextMut<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
420424
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
421425
}
422426

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxIndexMap;
44
use rustc_errors::MultiSpan;
55
use rustc_hir::{BindingMode, ByRef, HirId, Mutability};
66
use rustc_lint as lint;
7-
use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, Ty, TyCtxt};
7+
use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt};
88
use rustc_span::{Ident, Span};
99

1010
use crate::errors::{Rust2024IncompatiblePat, Rust2024IncompatiblePatSugg};
@@ -92,12 +92,12 @@ impl<'a> PatMigration<'a> {
9292
pub(super) fn visit_implicit_derefs<'tcx>(
9393
&mut self,
9494
pat_span: Span,
95-
adjustments: &[Ty<'tcx>],
95+
adjustments: &[ty::adjustment::PatAdjustment<'tcx>],
9696
) -> Option<(Span, Mutability)> {
9797
// Implicitly dereferencing references changes the default binding mode, but implicit derefs
9898
// of smart pointers do not. Thus, we only consider implicit derefs of reference types.
99-
let implicit_deref_mutbls = adjustments.iter().filter_map(|ref_ty| {
100-
if let &ty::Ref(_, _, mutbl) = ref_ty.kind() { Some(mutbl) } else { None }
99+
let implicit_deref_mutbls = adjustments.iter().filter_map(|adjust| {
100+
if let &ty::Ref(_, _, mutbl) = adjust.source.kind() { Some(mutbl) } else { None }
101101
});
102102

103103
if !self.info.suggest_eliding_modes {

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_middle::mir::interpret::LitToConstInput;
1717
use rustc_middle::thir::{
1818
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
1919
};
20-
use rustc_middle::ty::adjustment::PatAdjust;
20+
use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2121
use rustc_middle::ty::layout::IntegerExt;
2222
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt};
2323
use rustc_middle::{bug, span_bug};
@@ -63,15 +63,15 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
6363

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

6969
// Track the default binding mode for the Rust 2024 migration suggestion.
7070
// Implicitly dereferencing references changes the default binding mode, but implicit deref
7171
// patterns do not. Only track binding mode changes if a ref type is in the adjustments.
7272
let mut opt_old_mode_span = None;
7373
if let Some(s) = &mut self.rust_2024_migration
74-
&& adjustments.iter().any(|ty| ty.is_ref())
74+
&& adjustments.iter().any(|adjust| adjust.source.is_ref())
7575
{
7676
opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
7777
}
@@ -104,10 +104,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
104104
_ => self.lower_pattern_unadjusted(pat),
105105
};
106106

107-
let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| {
108-
debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty);
107+
let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
108+
debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
109109
let span = thir_pat.span;
110-
let kind = match ref_ty.pat_adjust_kind() {
110+
let kind = match adjust.kind {
111111
PatAdjust::BuiltinDeref => PatKind::Deref { subpattern: thir_pat },
112112
PatAdjust::OverloadedDeref => {
113113
let mutable = self.typeck_results.pat_has_ref_mut_binding(pat);
@@ -116,11 +116,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
116116
PatKind::DerefPattern { subpattern: thir_pat, mutability }
117117
}
118118
};
119-
Box::new(Pat { span, ty: *ref_ty, kind })
119+
Box::new(Pat { span, ty: adjust.source, kind })
120120
});
121121

122122
if let Some(s) = &mut self.rust_2024_migration
123-
&& adjustments.iter().any(|ty| ty.is_ref())
123+
&& adjustments.iter().any(|adjust| adjust.source.is_ref())
124124
{
125125
s.leave_ref(opt_old_mode_span);
126126
}

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

+1-1
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)