Skip to content

Commit a0d9c87

Browse files
committed
Inline calc_default_binding_mode
1 parent d4f880f commit a0d9c87

File tree

1 file changed

+66
-92
lines changed
  • compiler/rustc_hir_typeck/src

1 file changed

+66
-92
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 66 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
163163
enum AdjustMode {
164164
/// Peel off all immediate reference types.
165165
Peel,
166-
/// Reset binding mode to the initial mode.
167-
/// Used for destructuring assignment, where we don't want any match ergonomics.
168-
Reset,
169166
/// Pass on the input binding mode and expected type.
170167
Pass,
171168
}
@@ -322,6 +319,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
322319
#[instrument(level = "debug", skip(self, pat_info))]
323320
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
324321
let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
322+
#[cfg(debug_assertions)]
323+
if binding_mode == ByRef::Yes(Mutability::Mut)
324+
&& max_ref_mutbl != MutblCap::Mut
325+
&& self.downgrade_mut_inside_shared()
326+
{
327+
span_bug!(pat.span, "Pattern mutability cap violated!");
328+
}
325329

326330
let path_res = match pat.kind {
327331
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
@@ -330,8 +334,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
330334
_ => None,
331335
};
332336
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
333-
let (expected, binding_mode, max_ref_mutbl) =
334-
self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl);
337+
let (expected, binding_mode, max_ref_mutbl) = match adjust_mode {
338+
// When we perform destructuring assignment, we disable default match bindings, which
339+
// are unintuitive in this context.
340+
_ if !pat.default_binding_modes => (expected, ByRef::No, MutblCap::Mut),
341+
AdjustMode::Pass => (expected, binding_mode, max_ref_mutbl),
342+
// Peel off as many immediately nested `& mut?` from the expected type as possible
343+
// and return the new expected type and binding default binding mode.
344+
// The adjustments vector, if non-empty is stored in a table.
345+
AdjustMode::Peel => {
346+
let mut binding_mode = binding_mode;
347+
let mut max_ref_mutbl = max_ref_mutbl;
348+
let mut expected = self.try_structurally_resolve_type(pat.span, expected);
349+
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
350+
// for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
351+
// the `Some(5)` which is not of type Ref.
352+
//
353+
// For each ampersand peeled off, update the binding mode and push the original
354+
// type into the adjustments vector.
355+
//
356+
// See the examples in `ui/match-defbm*.rs`.
357+
let mut pat_adjustments = vec![];
358+
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
359+
debug!("inspecting {:?}", expected);
360+
361+
debug!("current discriminant is Ref, inserting implicit deref");
362+
// Preserve the reference type. We'll need it later during THIR lowering.
363+
pat_adjustments.push(expected);
364+
365+
expected = self.try_structurally_resolve_type(pat.span, inner_ty);
366+
binding_mode = ByRef::Yes(match binding_mode {
367+
// If default binding mode is by value, make it `ref` or `ref mut`
368+
// (depending on whether we observe `&` or `&mut`).
369+
ByRef::No |
370+
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
371+
ByRef::Yes(Mutability::Mut) => inner_mutability,
372+
// Once a `ref`, always a `ref`.
373+
// This is because a `& &mut` cannot mutate the underlying value.
374+
ByRef::Yes(Mutability::Not) => Mutability::Not,
375+
});
376+
}
377+
378+
if self.downgrade_mut_inside_shared() {
379+
binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl());
380+
}
381+
if binding_mode == ByRef::Yes(Mutability::Not) {
382+
max_ref_mutbl = MutblCap::Not;
383+
}
384+
385+
if !pat_adjustments.is_empty() {
386+
debug!("default binding mode is now {:?}", binding_mode);
387+
self.typeck_results
388+
.borrow_mut()
389+
.pat_adjustments_mut()
390+
.insert(pat.hir_id, pat_adjustments);
391+
}
392+
393+
(expected, binding_mode, max_ref_mutbl)
394+
}
395+
};
335396
let pat_info = PatInfo {
336397
binding_mode,
337398
max_ref_mutbl,
@@ -437,39 +498,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
437498
// `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
438499
}
439500

440-
/// Compute the new expected type and default binding mode from the old ones
441-
/// as well as the pattern form we are currently checking.
442-
fn calc_default_binding_mode(
443-
&self,
444-
pat: &'tcx Pat<'tcx>,
445-
expected: Ty<'tcx>,
446-
def_br: ByRef,
447-
adjust_mode: AdjustMode,
448-
max_ref_mutbl: MutblCap,
449-
) -> (Ty<'tcx>, ByRef, MutblCap) {
450-
#[cfg(debug_assertions)]
451-
if def_br == ByRef::Yes(Mutability::Mut)
452-
&& max_ref_mutbl != MutblCap::Mut
453-
&& self.downgrade_mut_inside_shared()
454-
{
455-
span_bug!(pat.span, "Pattern mutability cap violated!");
456-
}
457-
match adjust_mode {
458-
AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
459-
AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
460-
AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl),
461-
}
462-
}
463-
464501
/// How should the binding mode and expected type be adjusted?
465502
///
466503
/// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
467504
fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode {
468-
// When we perform destructuring assignment, we disable default match bindings, which are
469-
// unintuitive in this context.
470-
if !pat.default_binding_modes {
471-
return AdjustMode::Reset;
472-
}
473505
match &pat.kind {
474506
// Type checking these product-like types successfully always require
475507
// that the expected type be of those types and not reference types.
@@ -526,64 +558,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
526558
}
527559
}
528560

529-
/// Peel off as many immediately nested `& mut?` from the expected type as possible
530-
/// and return the new expected type and binding default binding mode.
531-
/// The adjustments vector, if non-empty is stored in a table.
532-
fn peel_off_references(
533-
&self,
534-
pat: &'tcx Pat<'tcx>,
535-
expected: Ty<'tcx>,
536-
mut def_br: ByRef,
537-
mut max_ref_mutbl: MutblCap,
538-
) -> (Ty<'tcx>, ByRef, MutblCap) {
539-
let mut expected = self.try_structurally_resolve_type(pat.span, expected);
540-
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
541-
// for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
542-
// the `Some(5)` which is not of type Ref.
543-
//
544-
// For each ampersand peeled off, update the binding mode and push the original
545-
// type into the adjustments vector.
546-
//
547-
// See the examples in `ui/match-defbm*.rs`.
548-
let mut pat_adjustments = vec![];
549-
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
550-
debug!("inspecting {:?}", expected);
551-
552-
debug!("current discriminant is Ref, inserting implicit deref");
553-
// Preserve the reference type. We'll need it later during THIR lowering.
554-
pat_adjustments.push(expected);
555-
556-
expected = self.try_structurally_resolve_type(pat.span, inner_ty);
557-
def_br = ByRef::Yes(match def_br {
558-
// If default binding mode is by value, make it `ref` or `ref mut`
559-
// (depending on whether we observe `&` or `&mut`).
560-
ByRef::No |
561-
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
562-
ByRef::Yes(Mutability::Mut) => inner_mutability,
563-
// Once a `ref`, always a `ref`.
564-
// This is because a `& &mut` cannot mutate the underlying value.
565-
ByRef::Yes(Mutability::Not) => Mutability::Not,
566-
});
567-
}
568-
569-
if self.downgrade_mut_inside_shared() {
570-
def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
571-
}
572-
if def_br == ByRef::Yes(Mutability::Not) {
573-
max_ref_mutbl = MutblCap::Not;
574-
}
575-
576-
if !pat_adjustments.is_empty() {
577-
debug!("default binding mode is now {:?}", def_br);
578-
self.typeck_results
579-
.borrow_mut()
580-
.pat_adjustments_mut()
581-
.insert(pat.hir_id, pat_adjustments);
582-
}
583-
584-
(expected, def_br, max_ref_mutbl)
585-
}
586-
587561
fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
588562
let ty = match &lt.kind {
589563
rustc_hir::PatExprKind::Lit { lit, negated } => {

0 commit comments

Comments
 (0)