diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-08-24 04:45:59 +0200 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-08-24 19:15:36 +0200 |
| commit | b4a4e718deee509408407a39b561461ece58355c (patch) | |
| tree | 19208bb0b580b1acecfc9d92f77d276bb0063059 /src | |
| parent | 3de221a862b064430bc8c5727e9e1346ad85c27e (diff) | |
| download | rust-b4a4e718deee509408407a39b561461ece58355c.tar.gz rust-b4a4e718deee509408407a39b561461ece58355c.zip | |
typeck/pat.rs: extract `check_pat_ref`.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_typeck/check/pat.rs | 99 |
1 files changed, 55 insertions, 44 deletions
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index f740dc73db5..55a9360b83f 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -111,50 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_box(pat.span, inner, expected, def_bm, discrim_span) } PatKind::Ref(ref inner, mutbl) => { - let expected = self.shallow_resolve(expected); - if self.check_dereferencable(pat.span, expected, &inner) { - // `demand::subtype` would be good enough, but using - // `eqtype` turns out to be equally general. See (*) - // below for details. - - // Take region, inner-type from expected type if we - // can, to avoid creating needless variables. This - // also helps with the bad interactions of the given - // hack detailed in (*) below. - debug!("check_pat_walk: expected={:?}", expected); - let (rptr_ty, inner_ty) = match expected.sty { - ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { - (expected, r_ty) - } - _ => { - let inner_ty = self.next_ty_var( - TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: inner.span, - } - ); - let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl }; - let region = self.next_region_var(infer::PatternRegion(pat.span)); - let rptr_ty = tcx.mk_ref(region, mt); - debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty); - let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty); - - // Look for a case like `fn foo(&foo: u32)` and suggest - // `fn foo(foo: &u32)` - if let Some(mut err) = err { - self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected); - err.emit(); - } - (rptr_ty, inner_ty) - } - }; - - self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); - rptr_ty - } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); - tcx.types.err - } + self.check_pat_ref(pat, inner, mutbl, expected, def_bm, discrim_span) } PatKind::Slice(ref before, ref slice, ref after) => { let expected_ty = self.structurally_resolved_type(pat.span, expected); @@ -1059,4 +1016,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.types.err } } + + fn check_pat_ref( + &self, + pat: &hir::Pat, + inner: &'tcx hir::Pat, + mutbl: hir::Mutability, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + discrim_span: Option<Span>, + ) -> Ty<'tcx> { + let tcx = self.tcx; + let expected = self.shallow_resolve(expected); + if self.check_dereferencable(pat.span, expected, &inner) { + // `demand::subtype` would be good enough, but using `eqtype` turns + // out to be equally general. See (*) below for details. + + // Take region, inner-type from expected type if we can, + // to avoid creating needless variables. This also helps with + // the bad interactions of the given hack detailed in (*) below. + debug!("check_pat_ref: expected={:?}", expected); + let (rptr_ty, inner_ty) = match expected.sty { + ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { + (expected, r_ty) + } + _ => { + let inner_ty = self.next_ty_var( + TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: inner.span, + } + ); + let mt = ty::TypeAndMut { ty: inner_ty, mutbl }; + let region = self.next_region_var(infer::PatternRegion(pat.span)); + let rptr_ty = tcx.mk_ref(region, mt); + debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty); + let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty); + + // Look for a case like `fn foo(&foo: u32)` and suggest + // `fn foo(foo: &u32)` + if let Some(mut err) = err { + self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected); + err.emit(); + } + (rptr_ty, inner_ty) + } + }; + + self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span); + rptr_ty + } else { + self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span); + tcx.types.err + } + } } |
