Skip to content

Commit c16248d

Browse files
committed
typeck/pat.rs: extract check_pat_ident.
1 parent d4afae9 commit c16248d

File tree

1 file changed

+63
-47
lines changed
  • src/librustc_typeck/check

1 file changed

+63
-47
lines changed

src/librustc_typeck/check/pat.rs

Lines changed: 63 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -77,53 +77,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7777
}
7878
}
7979
PatKind::Binding(ba, var_id, _, ref sub) => {
80-
let bm = if ba == hir::BindingAnnotation::Unannotated {
81-
def_bm
82-
} else {
83-
ty::BindingMode::convert(ba)
84-
};
85-
self.inh
86-
.tables
87-
.borrow_mut()
88-
.pat_binding_modes_mut()
89-
.insert(pat.hir_id, bm);
90-
debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
91-
let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
92-
match bm {
93-
ty::BindByReference(mutbl) => {
94-
// If the binding is like
95-
// ref x | ref const x | ref mut x
96-
// then `x` is assigned a value of type `&M T` where M is the mutability
97-
// and T is the expected type.
98-
let region_var = self.next_region_var(infer::PatternRegion(pat.span));
99-
let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
100-
let region_ty = tcx.mk_ref(region_var, mt);
101-
102-
// `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
103-
// required. However, we use equality, which is stronger. See (*) for
104-
// an explanation.
105-
self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span);
106-
}
107-
// Otherwise, the type of x is the expected type `T`.
108-
ty::BindByValue(_) => {
109-
// As above, `T <: typeof(x)` is required, but we
110-
// use equality, see (*) below.
111-
self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span);
112-
}
113-
}
114-
115-
// If there are multiple arms, make sure they all agree on
116-
// what the type of the binding `x` ought to be.
117-
if var_id != pat.hir_id {
118-
let vt = self.local_ty(pat.span, var_id).decl_ty;
119-
self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
120-
}
121-
122-
if let Some(ref p) = *sub {
123-
self.check_pat_walk(&p, expected, def_bm, discrim_span);
124-
}
125-
126-
local_ty
80+
let sub = sub.as_deref();
81+
self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, discrim_span)
12782
}
12883
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
12984
self.check_pat_tuple_struct(
@@ -611,6 +566,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
611566
Some(common_type)
612567
}
613568

569+
fn check_pat_ident(
570+
&self,
571+
pat: &hir::Pat,
572+
ba: hir::BindingAnnotation,
573+
var_id: hir::HirId,
574+
sub: Option<&'tcx hir::Pat>,
575+
expected: Ty<'tcx>,
576+
def_bm: ty::BindingMode,
577+
discrim_span: Option<Span>,
578+
) -> Ty<'tcx> {
579+
// Determine the binding mode...
580+
let bm = match ba {
581+
hir::BindingAnnotation::Unannotated => def_bm,
582+
_ => ty::BindingMode::convert(ba),
583+
};
584+
// ...and store it in a side table:
585+
self.inh
586+
.tables
587+
.borrow_mut()
588+
.pat_binding_modes_mut()
589+
.insert(pat.hir_id, bm);
590+
591+
debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
592+
593+
let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
594+
let eq_ty = match bm {
595+
ty::BindByReference(mutbl) => {
596+
// If the binding is like `ref x | ref const x | ref mut x`
597+
// then `x` is assigned a value of type `&M T` where M is the
598+
// mutability and T is the expected type.
599+
let region_var = self.next_region_var(infer::PatternRegion(pat.span));
600+
let mt = ty::TypeAndMut { ty: expected, mutbl };
601+
let region_ty = self.tcx.mk_ref(region_var, mt);
602+
603+
// `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)`
604+
// is required. However, we use equality, which is stronger.
605+
// See (*) for an explanation.
606+
region_ty
607+
}
608+
// Otherwise, the type of x is the expected type `T`.
609+
ty::BindByValue(_) => {
610+
// As above, `T <: typeof(x)` is required, but we use equality, see (*) below.
611+
expected
612+
}
613+
};
614+
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, discrim_span);
615+
616+
// If there are multiple arms, make sure they all agree on
617+
// what the type of the binding `x` ought to be.
618+
if var_id != pat.hir_id {
619+
let vt = self.local_ty(pat.span, var_id).decl_ty;
620+
self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
621+
}
622+
623+
if let Some(p) = sub {
624+
self.check_pat_walk(&p, expected, def_bm, discrim_span);
625+
}
626+
627+
local_ty
628+
}
629+
614630
fn borrow_pat_suggestion(
615631
&self,
616632
err: &mut DiagnosticBuilder<'_>,

0 commit comments

Comments
 (0)