Skip to content

Commit 38adb99

Browse files
committed
Reorganize check_pat_inner
1 parent 19950b5 commit 38adb99

File tree

1 file changed

+61
-57
lines changed
  • compiler/rustc_hir_typeck/src

1 file changed

+61
-57
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
337337
expected: Ty<'tcx>,
338338
pat_info: PatInfo<'tcx>,
339339
) {
340-
let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
340+
let PatInfo { mut binding_mode, mut max_ref_mutbl, current_depth, .. } = pat_info;
341341
#[cfg(debug_assertions)]
342342
if binding_mode == ByRef::Yes(Mutability::Mut)
343343
&& max_ref_mutbl != MutblCap::Mut
@@ -346,72 +346,76 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
346346
span_bug!(pat.span, "Pattern mutability cap violated!");
347347
}
348348

349-
let (expected, binding_mode, max_ref_mutbl) = match adjust_mode {
349+
if !pat.default_binding_modes {
350350
// When we perform destructuring assignment, we disable default match bindings, which
351351
// are unintuitive in this context.
352-
_ if !pat.default_binding_modes => (expected, ByRef::No, MutblCap::Mut),
353-
AdjustMode::Pass => (expected, binding_mode, max_ref_mutbl),
354-
// Peel an immediately nested `& mut?` from the expected type if possible and return the
355-
// new expected type and binding default binding mode.
356-
AdjustMode::Peel => {
357-
let expected = self.try_structurally_resolve_type(pat.span, expected);
358-
// Peel off a `&` or `&mut` from the scrutinee type. For each ampersand peeled off,
359-
// update the binding mode and push the original type into the adjustments vector.
360-
//
361-
// See the examples in `tests/ui/rfcs/rfc-2005-default-binding-mode`.
362-
if let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
363-
debug!("inspecting {:?}", expected);
364-
365-
debug!("current discriminant is Ref, inserting implicit deref");
366-
// Preserve the reference type. We'll need it later during THIR lowering.
367-
self.typeck_results
368-
.borrow_mut()
369-
.pat_adjustments_mut()
370-
.entry(pat.hir_id)
371-
.or_default()
372-
.push(expected);
373-
374-
let mut binding_mode = ByRef::Yes(match binding_mode {
375-
// If default binding mode is by value, make it `ref` or `ref mut`
376-
// (depending on whether we observe `&` or `&mut`).
377-
ByRef::No |
378-
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
379-
ByRef::Yes(Mutability::Mut) => inner_mutability,
380-
// Once a `ref`, always a `ref`.
381-
// This is because a `& &mut` cannot mutate the underlying value.
382-
ByRef::Yes(Mutability::Not) => Mutability::Not,
383-
});
384-
385-
if self.downgrade_mut_inside_shared() {
386-
binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl());
387-
}
388-
let mut max_ref_mutbl = max_ref_mutbl;
389-
if binding_mode == ByRef::Yes(Mutability::Not) {
390-
max_ref_mutbl = MutblCap::Not;
391-
}
392-
debug!("default binding mode is now {:?}", binding_mode);
393-
let pat_info = PatInfo { binding_mode, max_ref_mutbl, ..pat_info };
394-
return self.check_pat_inner(
395-
pat,
396-
opt_path_res,
397-
adjust_mode,
398-
inner_ty,
399-
pat_info,
400-
);
401-
} else {
402-
(expected, binding_mode, max_ref_mutbl)
403-
}
404-
}
352+
binding_mode = ByRef::No;
353+
max_ref_mutbl = MutblCap::Mut;
354+
};
355+
// Resolve type if needed.
356+
let expected = if let AdjustMode::Peel = adjust_mode
357+
&& pat.default_binding_modes
358+
{
359+
self.try_structurally_resolve_type(pat.span, expected)
360+
} else {
361+
expected
405362
};
363+
let old_pat_info = pat_info;
406364
let pat_info = PatInfo {
407365
binding_mode,
408366
max_ref_mutbl,
409-
top_info: ti,
410-
decl_origin: pat_info.decl_origin,
411367
current_depth: current_depth + 1,
368+
top_info: old_pat_info.top_info,
369+
decl_origin: old_pat_info.decl_origin,
412370
};
413371

414372
let ty = match pat.kind {
373+
// Peel off a `&` or `&mut` from the scrutinee type. See the examples in
374+
// `tests/ui/rfcs/rfc-2005-default-binding-mode`.
375+
_ if let AdjustMode::Peel = adjust_mode
376+
&& pat.default_binding_modes
377+
&& let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() =>
378+
{
379+
debug!("inspecting {:?}", expected);
380+
381+
debug!("current discriminant is Ref, inserting implicit deref");
382+
// Preserve the reference type. We'll need it later during THIR lowering.
383+
self.typeck_results
384+
.borrow_mut()
385+
.pat_adjustments_mut()
386+
.entry(pat.hir_id)
387+
.or_default()
388+
.push(expected);
389+
390+
binding_mode = ByRef::Yes(match binding_mode {
391+
// If default binding mode is by value, make it `ref` or `ref mut`
392+
// (depending on whether we observe `&` or `&mut`).
393+
ByRef::No |
394+
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
395+
ByRef::Yes(Mutability::Mut) => inner_mutability,
396+
// Once a `ref`, always a `ref`.
397+
// This is because a `& &mut` cannot mutate the underlying value.
398+
ByRef::Yes(Mutability::Not) => Mutability::Not,
399+
});
400+
401+
if self.downgrade_mut_inside_shared() {
402+
binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl());
403+
}
404+
if binding_mode == ByRef::Yes(Mutability::Not) {
405+
max_ref_mutbl = MutblCap::Not;
406+
}
407+
debug!("default binding mode is now {:?}", binding_mode);
408+
409+
// Use the old pat info to keep `current_depth` to its old value.
410+
let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info };
411+
return self.check_pat_inner(
412+
pat,
413+
opt_path_res,
414+
adjust_mode,
415+
inner_ty,
416+
new_pat_info,
417+
);
418+
}
415419
PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
416420
// We allow any type here; we ensure that the type is uninhabited during match checking.
417421
PatKind::Never => expected,

0 commit comments

Comments
 (0)