]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/check/_match.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / librustc_typeck / check / _match.rs
CommitLineData
1a4d82fc
JJ
1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
3157f602 11use hir::def::Def;
54a0048b 12use rustc::infer::{self, InferOk, TypeOrigin};
5bcae85e 13use hir::pat_util::EnumerateAndAdjustIterator;
54a0048b 14use rustc::ty::subst::Substs;
5bcae85e 15use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference, VariantKind};
a7813a04 16use check::{FnCtxt, Expectation};
92a42be0 17use lint;
1a4d82fc 18use util::nodemap::FnvHashMap;
1a4d82fc 19
1a4d82fc 20use std::collections::hash_map::Entry::{Occupied, Vacant};
3157f602 21use std::cmp;
1a4d82fc 22use syntax::ast;
3157f602 23use syntax::codemap::Spanned;
1a4d82fc 24use syntax::ptr::P;
3157f602 25use syntax_pos::Span;
1a4d82fc 26
54a0048b
SL
27use rustc::hir::{self, PatKind};
28use rustc::hir::print as pprust;
e9174d1e 29
3157f602 30impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
a7813a04
XL
31 pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
32 let tcx = self.tcx;
33
34 debug!("check_pat(pat={:?},expected={:?})", pat, expected);
35
36 match pat.node {
37 PatKind::Wild => {
38 self.write_ty(pat.id, expected);
39 }
40 PatKind::Lit(ref lt) => {
41 self.check_expr(&lt);
42 let expr_ty = self.expr_ty(&lt);
43
44 // Byte string patterns behave the same way as array patterns
45 // They can denote both statically and dynamically sized byte arrays
46 let mut pat_ty = expr_ty;
47 if let hir::ExprLit(ref lt) = lt.node {
48 if let ast::LitKind::ByteStr(_) = lt.node {
49 let expected_ty = self.structurally_resolved_type(pat.span, expected);
50 if let ty::TyRef(_, mt) = expected_ty.sty {
51 if let ty::TySlice(_) = mt.ty.sty {
52 pat_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
53 tcx.mk_slice(tcx.types.u8))
54 }
c34b1796
AL
55 }
56 }
57 }
c34b1796 58
a7813a04
XL
59 self.write_ty(pat.id, pat_ty);
60
61 // somewhat surprising: in this case, the subtyping
62 // relation goes the opposite way as the other
63 // cases. Actually what we really want is not a subtyping
64 // relation at all but rather that there exists a LUB (so
65 // that they can be compared). However, in practice,
66 // constants are always scalars or strings. For scalars
67 // subtyping is irrelevant, and for strings `expr_ty` is
68 // type is `&'static str`, so if we say that
69 //
70 // &'static str <: expected
71 //
72 // that's equivalent to there existing a LUB.
73 self.demand_suptype(pat.span, expected, pat_ty);
62682a34 74 }
a7813a04
XL
75 PatKind::Range(ref begin, ref end) => {
76 self.check_expr(begin);
77 self.check_expr(end);
78
79 let lhs_ty = self.expr_ty(begin);
80 let rhs_ty = self.expr_ty(end);
81
82 // Check that both end-points are of numeric or char type.
83 let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
84 let lhs_compat = numeric_or_char(lhs_ty);
85 let rhs_compat = numeric_or_char(rhs_ty);
86
87 if !lhs_compat || !rhs_compat {
88 let span = if !lhs_compat && !rhs_compat {
89 pat.span
90 } else if !lhs_compat {
91 begin.span
92 } else {
93 end.span
94 };
95
5bcae85e
SL
96 struct_span_err!(tcx.sess, span, E0029,
97 "only char and numeric types are allowed in range patterns")
98 .span_label(span, &format!("ranges require char or numeric types"))
99 .note(&format!("start type: {}", self.ty_to_string(lhs_ty)))
100 .note(&format!("end type: {}", self.ty_to_string(rhs_ty)))
101 .emit();
a7813a04
XL
102 return;
103 }
1a4d82fc 104
a7813a04
XL
105 // Now that we know the types can be unified we find the unified type and use
106 // it to type the entire expression.
107 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
62682a34 108
a7813a04 109 self.write_ty(pat.id, common_type);
62682a34 110
a7813a04
XL
111 // subtyping doesn't matter here, as the value is some kind of scalar
112 self.demand_eqtype(pat.span, expected, lhs_ty);
5bcae85e 113 self.demand_eqtype(pat.span, expected, rhs_ty);
1a4d82fc 114 }
3157f602 115 PatKind::Binding(bm, _, ref sub) => {
a7813a04
XL
116 let typ = self.local_ty(pat.span, pat.id);
117 match bm {
118 hir::BindByRef(mutbl) => {
119 // if the binding is like
120 // ref x | ref const x | ref mut x
121 // then `x` is assigned a value of type `&M T` where M is the mutability
122 // and T is the expected type.
123 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
124 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
125 let region_ty = tcx.mk_ref(tcx.mk_region(region_var), mt);
126
127 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
128 // required. However, we use equality, which is stronger. See (*) for
129 // an explanation.
130 self.demand_eqtype(pat.span, region_ty, typ);
131 }
132 // otherwise the type of x is the expected type T
133 hir::BindByValue(_) => {
134 // As above, `T <: typeof(x)` is required but we
135 // use equality, see (*) below.
136 self.demand_eqtype(pat.span, expected, typ);
137 }
138 }
1a4d82fc 139
a7813a04 140 self.write_ty(pat.id, typ);
1a4d82fc 141
a7813a04
XL
142 // if there are multiple arms, make sure they all agree on
143 // what the type of the binding `x` ought to be
3157f602
XL
144 match tcx.expect_def(pat.id) {
145 Def::Err => {}
146 Def::Local(_, var_id) => {
147 if var_id != pat.id {
148 let vt = self.local_ty(pat.span, var_id);
149 self.demand_eqtype(pat.span, vt, typ);
150 }
a7813a04 151 }
3157f602
XL
152 d => bug!("bad def for pattern binding `{:?}`", d)
153 }
1a4d82fc 154
3157f602
XL
155 if let Some(ref p) = *sub {
156 self.check_pat(&p, expected);
9cc50fc6 157 }
1a4d82fc 158 }
3157f602 159 PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
5bcae85e 160 self.check_pat_tuple_struct(pat, path, &subpats, ddpos, expected);
a7813a04 161 }
5bcae85e
SL
162 PatKind::Path(ref opt_qself, ref path) => {
163 let opt_qself_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
164 self.check_pat_path(pat, opt_qself_ty, path, expected);
a7813a04
XL
165 }
166 PatKind::Struct(ref path, ref fields, etc) => {
167 self.check_pat_struct(pat, path, fields, etc, expected);
168 }
3157f602
XL
169 PatKind::Tuple(ref elements, ddpos) => {
170 let mut expected_len = elements.len();
171 if ddpos.is_some() {
172 // Require known type only when `..` is present
173 if let ty::TyTuple(ref tys) =
174 self.structurally_resolved_type(pat.span, expected).sty {
175 expected_len = tys.len();
176 }
177 }
178 let max_len = cmp::max(expected_len, elements.len());
179
180 let element_tys: Vec<_> = (0 .. max_len).map(|_| self.next_ty_var()).collect();
a7813a04
XL
181 let pat_ty = tcx.mk_tup(element_tys.clone());
182 self.write_ty(pat.id, pat_ty);
183 self.demand_eqtype(pat.span, expected, pat_ty);
3157f602
XL
184 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
185 self.check_pat(elem, &element_tys[i]);
d9579d0f 186 }
a7813a04
XL
187 }
188 PatKind::Box(ref inner) => {
189 let inner_ty = self.next_ty_var();
190 let uniq_ty = tcx.mk_box(inner_ty);
191
192 if self.check_dereferencable(pat.span, expected, &inner) {
193 // Here, `demand::subtype` is good enough, but I don't
194 // think any errors can be introduced by using
195 // `demand::eqtype`.
196 self.demand_eqtype(pat.span, expected, uniq_ty);
197 self.write_ty(pat.id, uniq_ty);
198 self.check_pat(&inner, inner_ty);
d9579d0f 199 } else {
a7813a04
XL
200 self.write_error(pat.id);
201 self.check_pat(&inner, tcx.types.err);
d9579d0f
AL
202 }
203 }
a7813a04
XL
204 PatKind::Ref(ref inner, mutbl) => {
205 let expected = self.shallow_resolve(expected);
206 if self.check_dereferencable(pat.span, expected, &inner) {
207 // `demand::subtype` would be good enough, but using
208 // `eqtype` turns out to be equally general. See (*)
209 // below for details.
210
211 // Take region, inner-type from expected type if we
212 // can, to avoid creating needless variables. This
213 // also helps with the bad interactions of the given
214 // hack detailed in (*) below.
215 let (rptr_ty, inner_ty) = match expected.sty {
216 ty::TyRef(_, mt) if mt.mutbl == mutbl => {
217 (expected, mt.ty)
218 }
219 _ => {
220 let inner_ty = self.next_ty_var();
221 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
222 let region = self.next_region_var(infer::PatternRegion(pat.span));
223 let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
224 self.demand_eqtype(pat.span, expected, rptr_ty);
225 (rptr_ty, inner_ty)
226 }
227 };
b039eaaf 228
a7813a04
XL
229 self.write_ty(pat.id, rptr_ty);
230 self.check_pat(&inner, inner_ty);
231 } else {
232 self.write_error(pat.id);
233 self.check_pat(&inner, tcx.types.err);
234 }
235 }
236 PatKind::Vec(ref before, ref slice, ref after) => {
237 let expected_ty = self.structurally_resolved_type(pat.span, expected);
3157f602
XL
238 let (inner_ty, slice_ty) = match expected_ty.sty {
239 ty::TyArray(inner_ty, size) => {
a7813a04 240 let min_len = before.len() + after.len();
3157f602
XL
241 if slice.is_none() {
242 if min_len != size {
243 span_err!(tcx.sess, pat.span, E0527,
244 "pattern requires {} elements but array has {}",
245 min_len, size);
246 }
247 (inner_ty, tcx.types.err)
248 } else if let Some(rest) = size.checked_sub(min_len) {
249 (inner_ty, tcx.mk_array(inner_ty, rest))
250 } else {
251 span_err!(tcx.sess, pat.span, E0528,
252 "pattern requires at least {} elements but array has {}",
253 min_len, size);
254 (inner_ty, tcx.types.err)
a7813a04 255 }
3157f602
XL
256 }
257 ty::TySlice(inner_ty) => (inner_ty, expected_ty),
b039eaaf 258 _ => {
3157f602
XL
259 if !expected_ty.references_error() {
260 let mut err = struct_span_err!(
261 tcx.sess, pat.span, E0529,
262 "expected an array or slice, found `{}`",
263 expected_ty);
264 if let ty::TyRef(_, ty::TypeAndMut { mutbl: _, ty }) = expected_ty.sty {
265 match ty.sty {
266 ty::TyArray(..) | ty::TySlice(..) => {
267 err.help("the semantics of slice patterns changed \
268 recently; see issue #23121");
269 }
270 _ => {}
271 }
272 }
273 err.emit();
274 }
275 (tcx.types.err, tcx.types.err)
b039eaaf
SL
276 }
277 };
278
3157f602 279 self.write_ty(pat.id, expected_ty);
1a4d82fc 280
a7813a04
XL
281 for elt in before {
282 self.check_pat(&elt, inner_ty);
283 }
284 if let Some(ref slice) = *slice {
a7813a04
XL
285 self.check_pat(&slice, slice_ty);
286 }
287 for elt in after {
288 self.check_pat(&elt, inner_ty);
289 }
1a4d82fc
JJ
290 }
291 }
1a4d82fc 292
a7813a04
XL
293 // (*) In most of the cases above (literals and constants being
294 // the exception), we relate types using strict equality, evewn
295 // though subtyping would be sufficient. There are a few reasons
296 // for this, some of which are fairly subtle and which cost me
297 // (nmatsakis) an hour or two debugging to remember, so I thought
298 // I'd write them down this time.
299 //
300 // 1. There is no loss of expressiveness here, though it does
301 // cause some inconvenience. What we are saying is that the type
302 // of `x` becomes *exactly* what is expected. This can cause unnecessary
303 // errors in some cases, such as this one:
304 // it will cause errors in a case like this:
305 //
306 // ```
307 // fn foo<'x>(x: &'x int) {
308 // let a = 1;
309 // let mut z = x;
310 // z = &a;
311 // }
312 // ```
313 //
314 // The reason we might get an error is that `z` might be
315 // assigned a type like `&'x int`, and then we would have
316 // a problem when we try to assign `&a` to `z`, because
317 // the lifetime of `&a` (i.e., the enclosing block) is
318 // shorter than `'x`.
319 //
320 // HOWEVER, this code works fine. The reason is that the
321 // expected type here is whatever type the user wrote, not
322 // the initializer's type. In this case the user wrote
323 // nothing, so we are going to create a type variable `Z`.
324 // Then we will assign the type of the initializer (`&'x
325 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
326 // will instantiate `Z` as a type `&'0 int` where `'0` is
327 // a fresh region variable, with the constraint that `'x :
328 // '0`. So basically we're all set.
329 //
330 // Note that there are two tests to check that this remains true
331 // (`regions-reassign-{match,let}-bound-pointer.rs`).
332 //
333 // 2. Things go horribly wrong if we use subtype. The reason for
334 // THIS is a fairly subtle case involving bound regions. See the
335 // `givens` field in `region_inference`, as well as the test
336 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
337 // for details. Short version is that we must sometimes detect
338 // relationships between specific region variables and regions
339 // bound in a closure signature, and that detection gets thrown
340 // off when we substitute fresh region variables here to enable
341 // subtyping.
d9579d0f 342 }
d9579d0f 343
a7813a04 344 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
3157f602
XL
345 if let PatKind::Binding(..) = inner.node {
346 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) {
347 if let ty::TyTrait(..) = mt.ty.sty {
a7813a04
XL
348 // This is "x = SomeTrait" being reduced from
349 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
3157f602 350 span_err!(self.tcx.sess, span, E0033,
a7813a04
XL
351 "type `{}` cannot be dereferenced",
352 self.ty_to_string(expected));
3157f602 353 return false
a7813a04 354 }
3157f602 355 }
54a0048b 356 }
3157f602 357 true
a7813a04
XL
358 }
359}
54a0048b 360
a7813a04
XL
361impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
362 pub fn check_match(&self,
363 expr: &'gcx hir::Expr,
364 discrim: &'gcx hir::Expr,
365 arms: &'gcx [hir::Arm],
366 expected: Expectation<'tcx>,
367 match_src: hir::MatchSource) {
368 let tcx = self.tcx;
369
370 // Not entirely obvious: if matches may create ref bindings, we
371 // want to use the *precise* type of the discriminant, *not* some
372 // supertype, as the "discriminant type" (issue #23116).
373 let contains_ref_bindings = arms.iter()
374 .filter_map(|a| tcx.arm_contains_ref_binding(a))
375 .max_by_key(|m| match *m {
376 hir::MutMutable => 1,
377 hir::MutImmutable => 0,
378 });
379 let discrim_ty;
380 if let Some(m) = contains_ref_bindings {
381 self.check_expr_with_lvalue_pref(discrim, LvaluePreference::from_mutbl(m));
382 discrim_ty = self.expr_ty(discrim);
54a0048b 383 } else {
a7813a04
XL
384 // ...but otherwise we want to use any supertype of the
385 // discriminant. This is sort of a workaround, see note (*) in
386 // `check_pat` for some details.
387 discrim_ty = self.next_ty_var();
388 self.check_expr_has_type(discrim, discrim_ty);
54a0048b 389 };
1a4d82fc 390
a7813a04
XL
391 // Typecheck the patterns first, so that we get types for all the
392 // bindings.
393 for arm in arms {
a7813a04 394 for p in &arm.pats {
3157f602 395 self.check_pat(&p, discrim_ty);
a7813a04
XL
396 }
397 }
1a4d82fc 398
a7813a04
XL
399 // Now typecheck the blocks.
400 //
401 // The result of the match is the common supertype of all the
402 // arms. Start out the value as bottom, since it's the, well,
403 // bottom the type lattice, and we'll be moving up the lattice as
404 // we process each arm. (Note that any match with 0 arms is matching
405 // on any empty type and is therefore unreachable; should the flow
406 // of execution reach it, we will panic, so bottom is an appropriate
407 // type in that case)
408 let expected = expected.adjust_for_branches(self);
409 let mut result_ty = self.next_diverging_ty_var();
410 let coerce_first = match expected {
411 // We don't coerce to `()` so that if the match expression is a
412 // statement it's branches can have any consistent type. That allows
413 // us to give better error messages (pointing to a usually better
414 // arm for inconsistent arms or to the whole match when a `()` type
415 // is required).
416 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => {
417 ety
54a0048b 418 }
a7813a04 419 _ => result_ty
54a0048b 420 };
a7813a04
XL
421 for (i, arm) in arms.iter().enumerate() {
422 if let Some(ref e) = arm.guard {
423 self.check_expr_has_type(e, tcx.types.bool);
424 }
425 self.check_expr_with_expectation(&arm.body, expected);
426 let arm_ty = self.expr_ty(&arm.body);
1a4d82fc 427
a7813a04
XL
428 if result_ty.references_error() || arm_ty.references_error() {
429 result_ty = tcx.types.err;
430 continue;
431 }
1a4d82fc 432
a7813a04
XL
433 // Handle the fallback arm of a desugared if-let like a missing else.
434 let is_if_let_fallback = match match_src {
435 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
436 i == arms.len() - 1 && arm_ty.is_nil()
437 }
438 _ => false
439 };
1a4d82fc 440
a7813a04
XL
441 let origin = if is_if_let_fallback {
442 TypeOrigin::IfExpressionWithNoElse(expr.span)
443 } else {
444 TypeOrigin::MatchExpressionArm(expr.span, arm.body.span, match_src)
445 };
1a4d82fc 446
a7813a04
XL
447 let result = if is_if_let_fallback {
448 self.eq_types(true, origin, arm_ty, result_ty)
449 .map(|InferOk { obligations, .. }| {
450 // FIXME(#32730) propagate obligations
451 assert!(obligations.is_empty());
452 arm_ty
453 })
454 } else if i == 0 {
455 // Special-case the first arm, as it has no "previous expressions".
456 self.try_coerce(&arm.body, coerce_first)
457 } else {
458 let prev_arms = || arms[..i].iter().map(|arm| &*arm.body);
459 self.try_find_coercion_lub(origin, prev_arms, result_ty, &arm.body)
460 };
1a4d82fc 461
a7813a04
XL
462 result_ty = match result {
463 Ok(ty) => ty,
464 Err(e) => {
465 let (expected, found) = if is_if_let_fallback {
466 (arm_ty, result_ty)
467 } else {
468 (result_ty, arm_ty)
469 };
470 self.report_mismatched_types(origin, expected, found, e);
471 self.tcx.types.err
472 }
473 };
1a4d82fc 474 }
1a4d82fc 475
a7813a04 476 self.write_ty(expr.id, result_ty);
92a42be0
SL
477 }
478}
479
3157f602 480impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5bcae85e
SL
481 fn check_pat_struct(&self,
482 pat: &'gcx hir::Pat,
483 path: &hir::Path,
484 fields: &'gcx [Spanned<hir::FieldPat>],
485 etc: bool,
486 expected: Ty<'tcx>)
487 {
488 // Resolve the path and check the definition for errors.
489 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id,
490 pat.span) {
491 variant_ty
492 } else {
493 self.write_error(pat.id);
494 for field in fields {
495 self.check_pat(&field.node.pat, self.tcx.types.err);
9cc50fc6 496 }
5bcae85e 497 return;
a7813a04 498 };
9cc50fc6 499
5bcae85e
SL
500 // Type check the path.
501 self.demand_eqtype(pat.span, expected, pat_ty);
502
503 // Type check subpatterns.
504 let substs = match pat_ty.sty {
a7813a04
XL
505 ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
506 _ => span_bug!(pat.span, "struct variant is not an ADT")
507 };
5bcae85e 508 self.check_struct_pat_fields(pat.span, fields, variant, substs, etc);
d9579d0f
AL
509 }
510
5bcae85e 511 fn check_pat_path(&self,
a7813a04 512 pat: &hir::Pat,
5bcae85e 513 opt_self_ty: Option<Ty<'tcx>>,
a7813a04 514 path: &hir::Path,
5bcae85e 515 expected: Ty<'tcx>)
a7813a04 516 {
a7813a04 517 let tcx = self.tcx;
5bcae85e
SL
518 let report_unexpected_def = || {
519 span_err!(tcx.sess, pat.span, E0533,
520 "`{}` does not name a unit variant, unit struct or a constant",
521 pprust::path_to_string(path));
3157f602 522 self.write_error(pat.id);
a7813a04 523 };
1a4d82fc 524
5bcae85e
SL
525 // Resolve the path and check the definition for errors.
526 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
527 pat.id, pat.span);
528 match def {
529 Def::Err => {
530 self.set_tainted_by_errors();
531 self.write_error(pat.id);
532 return;
533 }
534 Def::Method(..) => {
535 report_unexpected_def();
536 return;
537 }
538 Def::Variant(..) | Def::Struct(..) => {
539 let variant = tcx.expect_variant_def(def);
540 if variant.kind != VariantKind::Unit {
541 report_unexpected_def();
542 return;
543 }
544 }
545 Def::Const(..) | Def::AssociatedConst(..) => {} // OK
546 _ => bug!("unexpected pattern definition {:?}", def)
1a4d82fc 547 }
1a4d82fc 548
5bcae85e
SL
549 // Type check the path.
550 let scheme = tcx.lookup_item_type(def.def_id());
551 let predicates = tcx.lookup_predicates(def.def_id());
552 let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
553 opt_ty, def, pat.span, pat.id);
554 self.demand_suptype(pat.span, expected, pat_ty);
555 }
7453a54e 556
5bcae85e
SL
557 fn check_pat_tuple_struct(&self,
558 pat: &hir::Pat,
559 path: &hir::Path,
560 subpats: &'gcx [P<hir::Pat>],
561 ddpos: Option<usize>,
562 expected: Ty<'tcx>)
563 {
564 let tcx = self.tcx;
565 let on_error = || {
a7813a04 566 self.write_error(pat.id);
3157f602
XL
567 for pat in subpats {
568 self.check_pat(&pat, tcx.types.err);
1a4d82fc 569 }
a7813a04 570 };
5bcae85e
SL
571 let report_unexpected_def = |is_lint| {
572 let msg = format!("`{}` does not name a tuple variant or a tuple struct",
573 pprust::path_to_string(path));
574 if is_lint {
575 tcx.sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
576 pat.id, pat.span, msg);
a7813a04 577 } else {
5bcae85e
SL
578 span_err!(tcx.sess, pat.span, E0164, "{}", msg);
579 on_error();
1a4d82fc 580 }
5bcae85e 581 };
a7813a04 582
5bcae85e
SL
583 // Resolve the path and check the definition for errors.
584 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(None, path, pat.id, pat.span);
585 let variant = match def {
586 Def::Err => {
587 self.set_tainted_by_errors();
588 on_error();
a7813a04 589 return;
1a4d82fc 590 }
5bcae85e
SL
591 Def::Const(..) | Def::AssociatedConst(..) | Def::Method(..) => {
592 report_unexpected_def(false);
593 return;
a7813a04 594 }
5bcae85e
SL
595 Def::Variant(..) | Def::Struct(..) => {
596 tcx.expect_variant_def(def)
a7813a04 597 }
5bcae85e
SL
598 _ => bug!("unexpected pattern definition {:?}", def)
599 };
600 if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
601 // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
602 // is allowed for backward compatibility.
603 report_unexpected_def(true);
604 } else if variant.kind != VariantKind::Tuple {
605 report_unexpected_def(false);
606 return;
a7813a04
XL
607 }
608
5bcae85e
SL
609 // Type check the path.
610 let scheme = tcx.lookup_item_type(def.def_id());
611 let scheme = if scheme.ty.is_fn() {
612 // Replace constructor type with constructed type for tuple struct patterns.
613 let fn_ret = tcx.no_late_bound_regions(&scheme.ty.fn_ret()).unwrap();
614 ty::TypeScheme { ty: fn_ret, generics: scheme.generics }
615 } else {
616 // Leave the type as is for unit structs (backward compatibility).
617 scheme
618 };
619 let predicates = tcx.lookup_predicates(def.def_id());
620 let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
621 opt_ty, def, pat.span, pat.id);
622 self.demand_eqtype(pat.span, expected, pat_ty);
623
624 // Type check subpatterns.
3157f602
XL
625 if subpats.len() == variant.fields.len() ||
626 subpats.len() < variant.fields.len() && ddpos.is_some() {
5bcae85e
SL
627 let substs = match pat_ty.sty {
628 ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
629 ref ty => bug!("unexpected pattern type {:?}", ty),
630 };
3157f602 631 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
5bcae85e 632 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
3157f602
XL
633 self.check_pat(&subpat, field_ty);
634 }
635 } else {
5bcae85e
SL
636 let subpats_ending = if subpats.len() == 1 {
637 ""
638 } else {
639 "s"
640 };
641 let fields_ending = if variant.fields.len() == 1 {
642 ""
643 } else {
644 "s"
645 };
646 struct_span_err!(tcx.sess, pat.span, E0023,
647 "this pattern has {} field{}, but the corresponding {} has {} field{}",
648 subpats.len(), subpats_ending, def.kind_name(),
649 variant.fields.len(), fields_ending)
650 .span_label(pat.span, &format!("expected {} field{}, found {}",
651 variant.fields.len(), fields_ending, subpats.len()))
652 .emit();
653 on_error();
a7813a04 654 }
1a4d82fc
JJ
655 }
656
a7813a04
XL
657 /// `path` is the AST path item naming the type of this struct.
658 /// `fields` is the field patterns of the struct pattern.
659 /// `struct_fields` describes the type of each field of the struct.
660 /// `struct_id` is the ID of the struct.
661 /// `etc` is true if the pattern said '...' and false otherwise.
662 pub fn check_struct_pat_fields(&self,
663 span: Span,
664 fields: &'gcx [Spanned<hir::FieldPat>],
665 variant: ty::VariantDef<'tcx>,
666 substs: &Substs<'tcx>,
667 etc: bool) {
668 let tcx = self.tcx;
669
670 // Index the struct fields' types.
671 let field_map = variant.fields
1a4d82fc 672 .iter()
a7813a04
XL
673 .map(|field| (field.name, field))
674 .collect::<FnvHashMap<_, _>>();
675
676 // Keep track of which fields have already appeared in the pattern.
677 let mut used_fields = FnvHashMap();
678
679 // Typecheck each field.
680 for &Spanned { node: ref field, span } in fields {
681 let field_ty = match used_fields.entry(field.name) {
682 Occupied(occupied) => {
683 let mut err = struct_span_err!(tcx.sess, span, E0025,
684 "field `{}` bound multiple times \
685 in the pattern",
686 field.name);
687 span_note!(&mut err, *occupied.get(),
688 "field `{}` previously bound here",
689 field.name);
690 err.emit();
691 tcx.types.err
692 }
693 Vacant(vacant) => {
694 vacant.insert(span);
695 field_map.get(&field.name)
696 .map(|f| self.field_ty(span, f, substs))
697 .unwrap_or_else(|| {
5bcae85e
SL
698 struct_span_err!(tcx.sess, span, E0026,
699 "struct `{}` does not have a field named `{}`",
700 tcx.item_path_str(variant.did),
701 field.name)
702 .span_label(span,
703 &format!("struct `{}` does not have field `{}`",
704 tcx.item_path_str(variant.did),
705 field.name))
706 .emit();
707
a7813a04
XL
708 tcx.types.err
709 })
710 }
711 };
712
713 self.check_pat(&field.pat, field_ty);
714 }
715
716 // Report an error if not all the fields were specified.
717 if !etc {
718 for field in variant.fields
719 .iter()
720 .filter(|field| !used_fields.contains_key(&field.name)) {
5bcae85e
SL
721 struct_span_err!(tcx.sess, span, E0027,
722 "pattern does not mention field `{}`",
723 field.name)
724 .span_label(span, &format!("missing field `{}`", field.name))
725 .emit();
a7813a04 726 }
1a4d82fc
JJ
727 }
728 }
729}