Skip to content

Commit f09f1a7

Browse files
committed
typeck/pat.rs: extract check_pat_slice.
1 parent b4a4e71 commit f09f1a7

File tree

1 file changed

+86
-73
lines changed
  • src/librustc_typeck/check

1 file changed

+86
-73
lines changed

src/librustc_typeck/check/pat.rs

Lines changed: 86 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5252
def_bm: ty::BindingMode,
5353
discrim_span: Option<Span>,
5454
) {
55-
let tcx = self.tcx;
56-
5755
debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
5856

5957
let path_resolution = match &pat.node {
@@ -114,77 +112,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
114112
self.check_pat_ref(pat, inner, mutbl, expected, def_bm, discrim_span)
115113
}
116114
PatKind::Slice(ref before, ref slice, ref after) => {
117-
let expected_ty = self.structurally_resolved_type(pat.span, expected);
118-
let (inner_ty, slice_ty) = match expected_ty.sty {
119-
ty::Array(inner_ty, size) => {
120-
if let Some(size) = size.try_eval_usize(tcx, self.param_env) {
121-
let min_len = before.len() as u64 + after.len() as u64;
122-
if slice.is_none() {
123-
if min_len != size {
124-
struct_span_err!(
125-
tcx.sess, pat.span, E0527,
126-
"pattern requires {} elements but array has {}",
127-
min_len, size)
128-
.span_label(pat.span, format!("expected {} elements", size))
129-
.emit();
130-
}
131-
(inner_ty, tcx.types.err)
132-
} else if let Some(rest) = size.checked_sub(min_len) {
133-
(inner_ty, tcx.mk_array(inner_ty, rest))
134-
} else {
135-
struct_span_err!(tcx.sess, pat.span, E0528,
136-
"pattern requires at least {} elements but array has {}",
137-
min_len, size)
138-
.span_label(pat.span,
139-
format!("pattern cannot match array of {} elements", size))
140-
.emit();
141-
(inner_ty, tcx.types.err)
142-
}
143-
} else {
144-
struct_span_err!(
145-
tcx.sess,
146-
pat.span,
147-
E0730,
148-
"cannot pattern-match on an array without a fixed length",
149-
).emit();
150-
(inner_ty, tcx.types.err)
151-
}
152-
}
153-
ty::Slice(inner_ty) => (inner_ty, expected_ty),
154-
_ => {
155-
if !expected_ty.references_error() {
156-
let mut err = struct_span_err!(
157-
tcx.sess, pat.span, E0529,
158-
"expected an array or slice, found `{}`",
159-
expected_ty);
160-
if let ty::Ref(_, ty, _) = expected_ty.sty {
161-
match ty.sty {
162-
ty::Array(..) | ty::Slice(..) => {
163-
err.help("the semantics of slice patterns changed \
164-
recently; see issue #62254");
165-
}
166-
_ => {}
167-
}
168-
}
169-
170-
err.span_label( pat.span,
171-
format!("pattern cannot match with input type `{}`", expected_ty)
172-
).emit();
173-
}
174-
(tcx.types.err, tcx.types.err)
175-
}
176-
};
177-
178-
for elt in before {
179-
self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
180-
}
181-
if let Some(ref slice) = *slice {
182-
self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span);
183-
}
184-
for elt in after {
185-
self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
186-
}
187-
expected_ty
115+
let slice = slice.as_deref();
116+
self.check_pat_slice(pat.span, before, slice, after, expected, def_bm, discrim_span)
188117
}
189118
};
190119

@@ -1070,4 +999,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1070999
tcx.types.err
10711000
}
10721001
}
1002+
1003+
fn check_pat_slice(
1004+
&self,
1005+
span: Span,
1006+
before: &'tcx [P<hir::Pat>],
1007+
slice: Option<&'tcx hir::Pat>,
1008+
after: &'tcx [P<hir::Pat>],
1009+
expected: Ty<'tcx>,
1010+
def_bm: ty::BindingMode,
1011+
discrim_span: Option<Span>,
1012+
) -> Ty<'tcx> {
1013+
let tcx = self.tcx;
1014+
let expected_ty = self.structurally_resolved_type(span, expected);
1015+
let (inner_ty, slice_ty) = match expected_ty.sty {
1016+
ty::Array(inner_ty, size) => {
1017+
if let Some(size) = size.try_eval_usize(tcx, self.param_env) {
1018+
let min_len = before.len() as u64 + after.len() as u64;
1019+
if slice.is_none() {
1020+
if min_len != size {
1021+
struct_span_err!(
1022+
tcx.sess, span, E0527,
1023+
"pattern requires {} elements but array has {}",
1024+
min_len, size
1025+
)
1026+
.span_label(span, format!("expected {} elements", size))
1027+
.emit();
1028+
}
1029+
(inner_ty, tcx.types.err)
1030+
} else if let Some(rest) = size.checked_sub(min_len) {
1031+
(inner_ty, tcx.mk_array(inner_ty, rest))
1032+
} else {
1033+
let msg = format!("pattern cannot match array of {} elements", size);
1034+
struct_span_err!(
1035+
tcx.sess, span, E0528,
1036+
"pattern requires at least {} elements but array has {}",
1037+
min_len, size
1038+
)
1039+
.span_label(span, msg)
1040+
.emit();
1041+
(inner_ty, tcx.types.err)
1042+
}
1043+
} else {
1044+
struct_span_err!(
1045+
tcx.sess, span, E0730,
1046+
"cannot pattern-match on an array without a fixed length",
1047+
)
1048+
.emit();
1049+
(inner_ty, tcx.types.err)
1050+
}
1051+
}
1052+
ty::Slice(inner_ty) => (inner_ty, expected_ty),
1053+
_ => {
1054+
if !expected_ty.references_error() {
1055+
let mut err = struct_span_err!(
1056+
tcx.sess, span, E0529,
1057+
"expected an array or slice, found `{}`",
1058+
expected_ty
1059+
);
1060+
if let ty::Ref(_, ty, _) = expected_ty.sty {
1061+
if let ty::Array(..) | ty::Slice(..) = ty.sty {
1062+
err.help("the semantics of slice patterns changed \
1063+
recently; see issue #62254");
1064+
}
1065+
}
1066+
1067+
let msg = format!("pattern cannot match with input type `{}`", expected_ty);
1068+
err.span_label(span, msg);
1069+
err.emit();
1070+
}
1071+
(tcx.types.err, tcx.types.err)
1072+
}
1073+
};
1074+
1075+
for elt in before {
1076+
self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
1077+
}
1078+
if let Some(slice) = slice {
1079+
self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span);
1080+
}
1081+
for elt in after {
1082+
self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
1083+
}
1084+
expected_ty
1085+
}
10731086
}

0 commit comments

Comments
 (0)