]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/check/_match.rs
Imported Upstream version 1.8.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
7453a54e 11use middle::def::{self, Def};
92a42be0 12use middle::infer::{self, TypeOrigin};
d9579d0f
AL
13use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
14use middle::pat_util::pat_is_resolved_const;
15use middle::privacy::{AllPublic, LastMod};
c34b1796 16use middle::subst::Substs;
9cc50fc6 17use middle::ty::{self, Ty, TypeFoldable, LvaluePreference};
1a4d82fc
JJ
18use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
19use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
e9174d1e 20use check::{check_expr_with_lvalue_pref};
d9579d0f 21use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
92a42be0 22use lint;
1a4d82fc
JJ
23use require_same_types;
24use util::nodemap::FnvHashMap;
92a42be0 25use session::Session;
1a4d82fc 26
c1a9b12d 27use std::cmp;
1a4d82fc
JJ
28use std::collections::hash_map::Entry::{Occupied, Vacant};
29use syntax::ast;
1a4d82fc 30use syntax::codemap::{Span, Spanned};
1a4d82fc
JJ
31use syntax::ptr::P;
32
7453a54e 33use rustc_front::hir::{self, PatKind};
e9174d1e
SL
34use rustc_front::print::pprust;
35use rustc_front::util as hir_util;
36
1a4d82fc 37pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
e9174d1e 38 pat: &'tcx hir::Pat,
1a4d82fc
JJ
39 expected: Ty<'tcx>)
40{
41 let fcx = pcx.fcx;
42 let tcx = pcx.fcx.ccx.tcx;
43
62682a34
SL
44 debug!("check_pat(pat={:?},expected={:?})",
45 pat,
46 expected);
1a4d82fc
JJ
47
48 match pat.node {
7453a54e 49 PatKind::Wild => {
1a4d82fc
JJ
50 fcx.write_ty(pat.id, expected);
51 }
7453a54e
SL
52 PatKind::Lit(ref lt) => {
53 check_expr(fcx, &lt);
54 let expr_ty = fcx.expr_ty(&lt);
c34b1796
AL
55
56 // Byte string patterns behave the same way as array patterns
57 // They can denote both statically and dynamically sized byte arrays
58 let mut pat_ty = expr_ty;
e9174d1e 59 if let hir::ExprLit(ref lt) = lt.node {
7453a54e 60 if let ast::LitKind::ByteStr(_) = lt.node {
c34b1796 61 let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
62682a34
SL
62 if let ty::TyRef(_, mt) = expected_ty.sty {
63 if let ty::TySlice(_) = mt.ty.sty {
c1a9b12d
SL
64 pat_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
65 tcx.mk_slice(tcx.types.u8))
c34b1796
AL
66 }
67 }
68 }
69 }
70
71 fcx.write_ty(pat.id, pat_ty);
1a4d82fc
JJ
72
73 // somewhat surprising: in this case, the subtyping
74 // relation goes the opposite way as the other
75 // cases. Actually what we really want is not a subtyping
76 // relation at all but rather that there exists a LUB (so
77 // that they can be compared). However, in practice,
78 // constants are always scalars or strings. For scalars
79 // subtyping is irrelevant, and for strings `expr_ty` is
80 // type is `&'static str`, so if we say that
81 //
82 // &'static str <: expected
83 //
84 // that's equivalent to there existing a LUB.
c34b1796 85 demand::suptype(fcx, pat.span, expected, pat_ty);
1a4d82fc 86 }
7453a54e 87 PatKind::Range(ref begin, ref end) => {
62682a34
SL
88 check_expr(fcx, begin);
89 check_expr(fcx, end);
90
91 let lhs_ty = fcx.expr_ty(begin);
92 let rhs_ty = fcx.expr_ty(end);
93
94 // Check that both end-points are of numeric or char type.
c1a9b12d 95 let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
62682a34
SL
96 let lhs_compat = numeric_or_char(lhs_ty);
97 let rhs_compat = numeric_or_char(rhs_ty);
98
99 if !lhs_compat || !rhs_compat {
100 let span = if !lhs_compat && !rhs_compat {
101 pat.span
102 } else if !lhs_compat {
103 begin.span
104 } else {
105 end.span
106 };
107
108 // Note: spacing here is intentional, we want a space before "start" and "end".
109 span_err!(tcx.sess, span, E0029,
110 "only char and numeric types are allowed in range patterns\n \
111 start type: {}\n end type: {}",
112 fcx.infcx().ty_to_string(lhs_ty),
113 fcx.infcx().ty_to_string(rhs_ty)
114 );
115 return;
116 }
117
118 // Check that the types of the end-points can be unified.
119 let types_unify = require_same_types(
120 tcx, Some(fcx.infcx()), false, pat.span, rhs_ty, lhs_ty,
121 || "mismatched types in range".to_string()
122 );
123
124 // It's ok to return without a message as `require_same_types` prints an error.
125 if !types_unify {
126 return;
1a4d82fc
JJ
127 }
128
62682a34
SL
129 // Now that we know the types can be unified we find the unified type and use
130 // it to type the entire expression.
131 let common_type = fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
132
133 fcx.write_ty(pat.id, common_type);
134
1a4d82fc
JJ
135 // subtyping doesn't matter here, as the value is some kind of scalar
136 demand::eqtype(fcx, pat.span, expected, lhs_ty);
137 }
7453a54e 138 PatKind::Path(..) | PatKind::Ident(..)
92a42be0 139 if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
9cc50fc6
SL
140 if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) {
141 let const_did = pat_def.def_id();
142 let const_scheme = tcx.lookup_item_type(const_did);
143 assert!(const_scheme.generics.is_empty());
144 let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
145 &Substs::empty(),
146 &const_scheme.ty);
147 fcx.write_ty(pat.id, const_ty);
148
149 // FIXME(#20489) -- we should limit the types here to scalars or something!
150
7453a54e 151 // As with PatKind::Lit, what we really want here is that there
9cc50fc6
SL
152 // exist a LUB, but for the cases that can occur, subtype
153 // is good enough.
154 demand::suptype(fcx, pat.span, expected, const_ty);
155 } else {
156 fcx.write_error(pat.id);
157 }
1a4d82fc 158 }
7453a54e 159 PatKind::Ident(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => {
1a4d82fc
JJ
160 let typ = fcx.local_ty(pat.span, pat.id);
161 match bm {
e9174d1e 162 hir::BindByRef(mutbl) => {
1a4d82fc
JJ
163 // if the binding is like
164 // ref x | ref const x | ref mut x
165 // then `x` is assigned a value of type `&M T` where M is the mutability
166 // and T is the expected type.
167 let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
c1a9b12d
SL
168 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
169 let region_ty = tcx.mk_ref(tcx.mk_region(region_var), mt);
1a4d82fc
JJ
170
171 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
172 // required. However, we use equality, which is stronger. See (*) for
173 // an explanation.
174 demand::eqtype(fcx, pat.span, region_ty, typ);
175 }
176 // otherwise the type of x is the expected type T
e9174d1e 177 hir::BindByValue(_) => {
1a4d82fc
JJ
178 // As above, `T <: typeof(x)` is required but we
179 // use equality, see (*) below.
180 demand::eqtype(fcx, pat.span, expected, typ);
181 }
182 }
183
184 fcx.write_ty(pat.id, typ);
185
186 // if there are multiple arms, make sure they all agree on
187 // what the type of the binding `x` ought to be
9cc50fc6
SL
188 if let Some(&canon_id) = pcx.map.get(&path.node.name) {
189 if canon_id != pat.id {
190 let ct = fcx.local_ty(pat.span, canon_id);
191 demand::eqtype(fcx, pat.span, ct, typ);
192 }
1a4d82fc 193
9cc50fc6 194 if let Some(ref p) = *sub {
7453a54e 195 check_pat(pcx, &p, expected);
9cc50fc6 196 }
1a4d82fc
JJ
197 }
198 }
7453a54e 199 PatKind::Ident(_, ref path, _) => {
e9174d1e 200 let path = hir_util::ident_to_path(path.span, path.node);
92a42be0 201 check_pat_enum(pcx, pat, &path, Some(&[]), expected, false);
1a4d82fc 202 }
7453a54e
SL
203 PatKind::TupleStruct(ref path, ref subpats) => {
204 check_pat_enum(pcx, pat, path, subpats.as_ref().map(|v| &v[..]), expected, true);
205 }
206 PatKind::Path(ref path) => {
207 check_pat_enum(pcx, pat, path, Some(&[]), expected, false);
1a4d82fc 208 }
7453a54e 209 PatKind::QPath(ref qself, ref path) => {
d9579d0f
AL
210 let self_ty = fcx.to_ty(&qself.ty);
211 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
7453a54e 212 if d.base_def == Def::Err {
9cc50fc6
SL
213 fcx.write_error(pat.id);
214 return;
215 }
d9579d0f
AL
216 d
217 } else if qself.position == 0 {
b039eaaf
SL
218 // This is just a sentinel for finish_resolving_def_to_ty.
219 let sentinel = fcx.tcx().map.local_def_id(ast::CRATE_NODE_ID);
d9579d0f 220 def::PathResolution {
7453a54e 221 base_def: Def::Mod(sentinel),
d9579d0f
AL
222 last_private: LastMod(AllPublic),
223 depth: path.segments.len()
224 }
225 } else {
9cc50fc6
SL
226 debug!("unbound path {:?}", pat);
227 fcx.write_error(pat.id);
228 return;
d9579d0f
AL
229 };
230 if let Some((opt_ty, segments, def)) =
231 resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty),
232 path, pat.span, pat.id) {
233 if check_assoc_item_is_const(pcx, def, pat.span) {
c1a9b12d
SL
234 let scheme = tcx.lookup_item_type(def.def_id());
235 let predicates = tcx.lookup_predicates(def.def_id());
d9579d0f
AL
236 instantiate_path(fcx, segments,
237 scheme, &predicates,
238 opt_ty, def, pat.span, pat.id);
239 let const_ty = fcx.node_ty(pat.id);
240 demand::suptype(fcx, pat.span, expected, const_ty);
241 } else {
242 fcx.write_error(pat.id)
243 }
244 }
245 }
7453a54e 246 PatKind::Struct(ref path, ref fields, etc) => {
85aaf69f 247 check_pat_struct(pcx, pat, path, fields, etc, expected);
1a4d82fc 248 }
7453a54e 249 PatKind::Tup(ref elements) => {
1a4d82fc 250 let element_tys: Vec<_> =
85aaf69f 251 (0..elements.len()).map(|_| fcx.infcx().next_ty_var())
1a4d82fc 252 .collect();
c1a9b12d 253 let pat_ty = tcx.mk_tup(element_tys.clone());
1a4d82fc
JJ
254 fcx.write_ty(pat.id, pat_ty);
255 demand::eqtype(fcx, pat.span, expected, pat_ty);
62682a34 256 for (element_pat, element_ty) in elements.iter().zip(element_tys) {
7453a54e 257 check_pat(pcx, &element_pat, element_ty);
1a4d82fc
JJ
258 }
259 }
7453a54e 260 PatKind::Box(ref inner) => {
1a4d82fc 261 let inner_ty = fcx.infcx().next_ty_var();
c1a9b12d 262 let uniq_ty = tcx.mk_box(inner_ty);
1a4d82fc 263
7453a54e 264 if check_dereferencable(pcx, pat.span, expected, &inner) {
1a4d82fc
JJ
265 // Here, `demand::subtype` is good enough, but I don't
266 // think any errors can be introduced by using
267 // `demand::eqtype`.
268 demand::eqtype(fcx, pat.span, expected, uniq_ty);
269 fcx.write_ty(pat.id, uniq_ty);
7453a54e 270 check_pat(pcx, &inner, inner_ty);
1a4d82fc
JJ
271 } else {
272 fcx.write_error(pat.id);
7453a54e 273 check_pat(pcx, &inner, tcx.types.err);
1a4d82fc
JJ
274 }
275 }
7453a54e 276 PatKind::Ref(ref inner, mutbl) => {
b039eaaf 277 let expected = fcx.infcx().shallow_resolve(expected);
7453a54e 278 if check_dereferencable(pcx, pat.span, expected, &inner) {
1a4d82fc
JJ
279 // `demand::subtype` would be good enough, but using
280 // `eqtype` turns out to be equally general. See (*)
281 // below for details.
b039eaaf
SL
282
283 // Take region, inner-type from expected type if we
284 // can, to avoid creating needless variables. This
285 // also helps with the bad interactions of the given
286 // hack detailed in (*) below.
287 let (rptr_ty, inner_ty) = match expected.sty {
288 ty::TyRef(_, mt) if mt.mutbl == mutbl => {
289 (expected, mt.ty)
290 }
291 _ => {
292 let inner_ty = fcx.infcx().next_ty_var();
293 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
294 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
295 let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
296 demand::eqtype(fcx, pat.span, expected, rptr_ty);
297 (rptr_ty, inner_ty)
298 }
299 };
300
1a4d82fc 301 fcx.write_ty(pat.id, rptr_ty);
7453a54e 302 check_pat(pcx, &inner, inner_ty);
1a4d82fc
JJ
303 } else {
304 fcx.write_error(pat.id);
7453a54e 305 check_pat(pcx, &inner, tcx.types.err);
1a4d82fc
JJ
306 }
307 }
7453a54e 308 PatKind::Vec(ref before, ref slice, ref after) => {
1a4d82fc
JJ
309 let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
310 let inner_ty = fcx.infcx().next_ty_var();
311 let pat_ty = match expected_ty.sty {
c1a9b12d 312 ty::TyArray(_, size) => tcx.mk_array(inner_ty, {
1a4d82fc
JJ
313 let min_len = before.len() + after.len();
314 match *slice {
315 Some(_) => cmp::max(min_len, size),
316 None => min_len
317 }
c1a9b12d 318 }),
1a4d82fc
JJ
319 _ => {
320 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
c1a9b12d
SL
321 tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
322 ty: tcx.mk_slice(inner_ty),
e9174d1e
SL
323 mutbl: expected_ty.builtin_deref(true, ty::NoPreference).map(|mt| mt.mutbl)
324 .unwrap_or(hir::MutImmutable)
1a4d82fc
JJ
325 })
326 }
327 };
328
329 fcx.write_ty(pat.id, pat_ty);
330
331 // `demand::subtype` would be good enough, but using
332 // `eqtype` turns out to be equally general. See (*)
333 // below for details.
334 demand::eqtype(fcx, pat.span, expected, pat_ty);
335
85aaf69f 336 for elt in before {
7453a54e 337 check_pat(pcx, &elt, inner_ty);
1a4d82fc
JJ
338 }
339 if let Some(ref slice) = *slice {
340 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
e9174d1e
SL
341 let mutbl = expected_ty.builtin_deref(true, ty::NoPreference)
342 .map_or(hir::MutImmutable, |mt| mt.mutbl);
1a4d82fc 343
c1a9b12d
SL
344 let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
345 ty: tcx.mk_slice(inner_ty),
1a4d82fc
JJ
346 mutbl: mutbl
347 });
7453a54e 348 check_pat(pcx, &slice, slice_ty);
1a4d82fc 349 }
85aaf69f 350 for elt in after {
7453a54e 351 check_pat(pcx, &elt, inner_ty);
1a4d82fc
JJ
352 }
353 }
1a4d82fc
JJ
354 }
355
356
357 // (*) In most of the cases above (literals and constants being
358 // the exception), we relate types using strict equality, evewn
359 // though subtyping would be sufficient. There are a few reasons
360 // for this, some of which are fairly subtle and which cost me
361 // (nmatsakis) an hour or two debugging to remember, so I thought
362 // I'd write them down this time.
363 //
c34b1796
AL
364 // 1. There is no loss of expressiveness here, though it does
365 // cause some inconvenience. What we are saying is that the type
366 // of `x` becomes *exactly* what is expected. This can cause unnecessary
367 // errors in some cases, such as this one:
368 // it will cause errors in a case like this:
1a4d82fc
JJ
369 //
370 // ```
371 // fn foo<'x>(x: &'x int) {
372 // let a = 1;
373 // let mut z = x;
374 // z = &a;
375 // }
376 // ```
377 //
378 // The reason we might get an error is that `z` might be
379 // assigned a type like `&'x int`, and then we would have
380 // a problem when we try to assign `&a` to `z`, because
381 // the lifetime of `&a` (i.e., the enclosing block) is
382 // shorter than `'x`.
383 //
384 // HOWEVER, this code works fine. The reason is that the
385 // expected type here is whatever type the user wrote, not
386 // the initializer's type. In this case the user wrote
387 // nothing, so we are going to create a type variable `Z`.
388 // Then we will assign the type of the initializer (`&'x
389 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
390 // will instantiate `Z` as a type `&'0 int` where `'0` is
391 // a fresh region variable, with the constraint that `'x :
392 // '0`. So basically we're all set.
393 //
394 // Note that there are two tests to check that this remains true
395 // (`regions-reassign-{match,let}-bound-pointer.rs`).
396 //
397 // 2. Things go horribly wrong if we use subtype. The reason for
398 // THIS is a fairly subtle case involving bound regions. See the
399 // `givens` field in `region_inference`, as well as the test
400 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
401 // for details. Short version is that we must sometimes detect
402 // relationships between specific region variables and regions
403 // bound in a closure signature, and that detection gets thrown
404 // off when we substitute fresh region variables here to enable
405 // subtyping.
406}
407
7453a54e 408fn check_assoc_item_is_const(pcx: &pat_ctxt, def: Def, span: Span) -> bool {
d9579d0f 409 match def {
7453a54e
SL
410 Def::AssociatedConst(..) => true,
411 Def::Method(..) => {
d9579d0f
AL
412 span_err!(pcx.fcx.ccx.tcx.sess, span, E0327,
413 "associated items in match patterns must be constants");
414 false
415 }
416 _ => {
417 pcx.fcx.ccx.tcx.sess.span_bug(span, "non-associated item in
418 check_assoc_item_is_const");
419 }
420 }
421}
422
1a4d82fc
JJ
423pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
424 span: Span, expected: Ty<'tcx>,
e9174d1e 425 inner: &hir::Pat) -> bool {
1a4d82fc
JJ
426 let fcx = pcx.fcx;
427 let tcx = pcx.fcx.ccx.tcx;
92a42be0 428 if pat_is_binding(&tcx.def_map.borrow(), inner) {
1a4d82fc 429 let expected = fcx.infcx().shallow_resolve(expected);
e9174d1e 430 expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty {
62682a34 431 ty::TyTrait(_) => {
1a4d82fc
JJ
432 // This is "x = SomeTrait" being reduced from
433 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
434 span_err!(tcx.sess, span, E0033,
435 "type `{}` cannot be dereferenced",
436 fcx.infcx().ty_to_string(expected));
437 false
438 }
439 _ => true
440 })
441 } else {
442 true
443 }
444}
445
446pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
e9174d1e
SL
447 expr: &'tcx hir::Expr,
448 discrim: &'tcx hir::Expr,
449 arms: &'tcx [hir::Arm],
1a4d82fc 450 expected: Expectation<'tcx>,
e9174d1e 451 match_src: hir::MatchSource) {
1a4d82fc
JJ
452 let tcx = fcx.ccx.tcx;
453
c34b1796
AL
454 // Not entirely obvious: if matches may create ref bindings, we
455 // want to use the *precise* type of the discriminant, *not* some
456 // supertype, as the "discriminant type" (issue #23116).
62682a34
SL
457 let contains_ref_bindings = arms.iter()
458 .filter_map(|a| tcx.arm_contains_ref_binding(a))
92a42be0 459 .max_by_key(|m| match *m {
e9174d1e
SL
460 hir::MutMutable => 1,
461 hir::MutImmutable => 0,
62682a34 462 });
c34b1796 463 let discrim_ty;
62682a34
SL
464 if let Some(m) = contains_ref_bindings {
465 check_expr_with_lvalue_pref(fcx, discrim, LvaluePreference::from_mutbl(m));
c34b1796
AL
466 discrim_ty = fcx.expr_ty(discrim);
467 } else {
468 // ...but otherwise we want to use any supertype of the
469 // discriminant. This is sort of a workaround, see note (*) in
470 // `check_pat` for some details.
471 discrim_ty = fcx.infcx().next_ty_var();
472 check_expr_has_type(fcx, discrim, discrim_ty);
473 };
1a4d82fc
JJ
474
475 // Typecheck the patterns first, so that we get types for all the
476 // bindings.
85aaf69f 477 for arm in arms {
1a4d82fc
JJ
478 let mut pcx = pat_ctxt {
479 fcx: fcx,
7453a54e 480 map: pat_id_map(&tcx.def_map, &arm.pats[0]),
1a4d82fc 481 };
85aaf69f 482 for p in &arm.pats {
7453a54e 483 check_pat(&mut pcx, &p, discrim_ty);
1a4d82fc
JJ
484 }
485 }
486
487 // Now typecheck the blocks.
488 //
489 // The result of the match is the common supertype of all the
490 // arms. Start out the value as bottom, since it's the, well,
491 // bottom the type lattice, and we'll be moving up the lattice as
492 // we process each arm. (Note that any match with 0 arms is matching
493 // on any empty type and is therefore unreachable; should the flow
494 // of execution reach it, we will panic, so bottom is an appropriate
495 // type in that case)
496 let expected = expected.adjust_for_branches(fcx);
497 let result_ty = arms.iter().fold(fcx.infcx().next_diverging_ty_var(), |result_ty, arm| {
498 let bty = match expected {
499 // We don't coerce to `()` so that if the match expression is a
500 // statement it's branches can have any consistent type. That allows
501 // us to give better error messages (pointing to a usually better
502 // arm for inconsistent arms or to the whole match when a `()` type
503 // is required).
c1a9b12d 504 Expectation::ExpectHasType(ety) if ety != fcx.tcx().mk_nil() => {
7453a54e 505 check_expr_coercable_to_type(fcx, &arm.body, ety);
1a4d82fc
JJ
506 ety
507 }
508 _ => {
7453a54e 509 check_expr_with_expectation(fcx, &arm.body, expected);
1a4d82fc
JJ
510 fcx.node_ty(arm.body.id)
511 }
512 };
513
514 if let Some(ref e) = arm.guard {
7453a54e 515 check_expr_has_type(fcx, &e, tcx.types.bool);
1a4d82fc
JJ
516 }
517
c1a9b12d 518 if result_ty.references_error() || bty.references_error() {
1a4d82fc
JJ
519 tcx.types.err
520 } else {
521 let (origin, expected, found) = match match_src {
522 /* if-let construct without an else block */
e9174d1e 523 hir::MatchSource::IfLetDesugar { contains_else_clause }
1a4d82fc 524 if !contains_else_clause => (
92a42be0 525 TypeOrigin::IfExpressionWithNoElse(expr.span),
1a4d82fc
JJ
526 bty,
527 result_ty,
528 ),
529 _ => (
92a42be0 530 TypeOrigin::MatchExpressionArm(expr.span, arm.body.span, match_src),
1a4d82fc
JJ
531 result_ty,
532 bty,
533 ),
534 };
535
536 infer::common_supertype(
537 fcx.infcx(),
538 origin,
539 true,
540 expected,
541 found,
542 )
543 }
544 });
545
546 fcx.write_ty(expr.id, result_ty);
547}
548
549pub struct pat_ctxt<'a, 'tcx: 'a> {
550 pub fcx: &'a FnCtxt<'a, 'tcx>,
551 pub map: PatIdMap,
552}
553
e9174d1e
SL
554pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
555 path: &hir::Path, fields: &'tcx [Spanned<hir::FieldPat>],
1a4d82fc
JJ
556 etc: bool, expected: Ty<'tcx>) {
557 let fcx = pcx.fcx;
558 let tcx = pcx.fcx.ccx.tcx;
559
c34b1796 560 let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
b039eaaf 561 let variant = match fcx.def_struct_variant(def, path.span) {
e9174d1e
SL
562 Some((_, variant)) => variant,
563 None => {
1a4d82fc 564 let name = pprust::path_to_string(path);
e9174d1e
SL
565 span_err!(tcx.sess, pat.span, E0163,
566 "`{}` does not name a struct or a struct variant", name);
1a4d82fc
JJ
567 fcx.write_error(pat.id);
568
85aaf69f 569 for field in fields {
e9174d1e 570 check_pat(pcx, &field.node.pat, tcx.types.err);
1a4d82fc
JJ
571 }
572 return;
1a4d82fc
JJ
573 }
574 };
575
e9174d1e
SL
576 let pat_ty = pcx.fcx.instantiate_type(def.def_id(), path);
577 let item_substs = match pat_ty.sty {
578 ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
579 _ => tcx.sess.span_bug(pat.span, "struct variant is not an ADT")
580 };
1a4d82fc 581 demand::eqtype(fcx, pat.span, expected, pat_ty);
e9174d1e 582 check_struct_pat_fields(pcx, pat.span, fields, variant, &item_substs, etc);
1a4d82fc 583
e9174d1e
SL
584 fcx.write_ty(pat.id, pat_ty);
585 fcx.write_substs(pat.id, ty::ItemSubsts { substs: item_substs.clone() });
1a4d82fc
JJ
586}
587
92a42be0
SL
588// This function exists due to the warning "diagnostic code E0164 already used"
589fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: bool) {
590 let name = pprust::path_to_string(path);
591 let msg = format!("`{}` does not name a tuple variant or a tuple struct", name);
592 if lint {
92a42be0
SL
593 sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
594 pat.id,
595 pat.span,
9cc50fc6 596 msg);
92a42be0
SL
597 } else {
598 span_err!(sess, pat.span, E0164, "{}", msg);
599 }
600}
601
7453a54e
SL
602fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
603 pat: &hir::Pat,
604 path: &hir::Path,
605 subpats: Option<&'tcx [P<hir::Pat>]>,
606 expected: Ty<'tcx>,
607 is_tuple_struct_pat: bool)
85aaf69f 608{
1a4d82fc
JJ
609 // Typecheck the path.
610 let fcx = pcx.fcx;
611 let tcx = pcx.fcx.ccx.tcx;
612
9cc50fc6 613 let path_res = match tcx.def_map.borrow().get(&pat.id) {
7453a54e 614 Some(&path_res) if path_res.base_def != Def::Err => path_res,
9cc50fc6
SL
615 _ => {
616 fcx.write_error(pat.id);
617
618 if let Some(subpats) = subpats {
619 for pat in subpats {
7453a54e 620 check_pat(pcx, &pat, tcx.types.err);
9cc50fc6
SL
621 }
622 }
623
624 return;
625 }
626 };
d9579d0f
AL
627
628 let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(fcx, path_res,
629 None, path,
630 pat.span, pat.id) {
631 Some(resolution) => resolution,
632 // Error handling done inside resolve_ty_and_def_ufcs, so if
633 // resolution fails just return.
634 None => {return;}
635 };
636
637 // Items that were partially resolved before should have been resolved to
638 // associated constants (i.e. not methods).
639 if path_res.depth != 0 && !check_assoc_item_is_const(pcx, def, pat.span) {
640 fcx.write_error(pat.id);
641 return;
642 }
643
1a4d82fc
JJ
644 let enum_def = def.variant_def_ids()
645 .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
646
c1a9b12d
SL
647 let ctor_scheme = tcx.lookup_item_type(enum_def);
648 let ctor_predicates = tcx.lookup_predicates(enum_def);
649 let path_scheme = if ctor_scheme.ty.is_fn() {
650 let fn_ret = tcx.no_late_bound_regions(&ctor_scheme.ty.fn_ret()).unwrap();
1a4d82fc
JJ
651 ty::TypeScheme {
652 ty: fn_ret.unwrap(),
653 generics: ctor_scheme.generics,
654 }
655 } else {
656 ctor_scheme
657 };
d9579d0f 658 instantiate_path(pcx.fcx, segments,
c34b1796 659 path_scheme, &ctor_predicates,
d9579d0f
AL
660 opt_ty, def, pat.span, pat.id);
661
92a42be0
SL
662 let report_bad_struct_kind = |is_warning| {
663 bad_struct_kind_err(tcx.sess, pat, path, is_warning);
664 if is_warning { return; }
665 fcx.write_error(pat.id);
666 if let Some(subpats) = subpats {
667 for pat in subpats {
7453a54e 668 check_pat(pcx, &pat, tcx.types.err);
92a42be0
SL
669 }
670 }
671 };
672
d9579d0f
AL
673 // If we didn't have a fully resolved path to start with, we had an
674 // associated const, and we should quit now, since the rest of this
675 // function uses checks specific to structs and enums.
676 if path_res.depth != 0 {
92a42be0
SL
677 if is_tuple_struct_pat {
678 report_bad_struct_kind(false);
679 } else {
680 let pat_ty = fcx.node_ty(pat.id);
681 demand::suptype(fcx, pat.span, expected, pat_ty);
682 }
d9579d0f
AL
683 return;
684 }
1a4d82fc
JJ
685
686 let pat_ty = fcx.node_ty(pat.id);
687 demand::eqtype(fcx, pat.span, expected, pat_ty);
688
689 let real_path_ty = fcx.node_ty(pat.id);
7453a54e
SL
690 let (kind_name, variant, expected_substs) = match real_path_ty.sty {
691 ty::TyEnum(enum_def, expected_substs) => {
e9174d1e 692 let variant = enum_def.variant_of_def(def);
7453a54e 693 ("variant", variant, expected_substs)
1a4d82fc 694 }
e9174d1e 695 ty::TyStruct(struct_def, expected_substs) => {
92a42be0 696 let variant = struct_def.struct_variant();
7453a54e 697 ("struct", variant, expected_substs)
1a4d82fc
JJ
698 }
699 _ => {
92a42be0 700 report_bad_struct_kind(false);
1a4d82fc
JJ
701 return;
702 }
703 };
704
7453a54e
SL
705 match (is_tuple_struct_pat, variant.kind()) {
706 (true, ty::VariantKind::Unit) => {
707 // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
708 // is allowed for backward compatibility.
709 report_bad_struct_kind(true);
710 }
711 (_, ty::VariantKind::Struct) => {
712 report_bad_struct_kind(false);
713 return
714 }
715 _ => {}
716 }
717
85aaf69f 718 if let Some(subpats) = subpats {
7453a54e
SL
719 if subpats.len() == variant.fields.len() {
720 for (subpat, field) in subpats.iter().zip(&variant.fields) {
721 let field_ty = fcx.field_ty(subpat.span, field, expected_substs);
722 check_pat(pcx, &subpat, field_ty);
1a4d82fc 723 }
7453a54e 724 } else if variant.fields.is_empty() {
1a4d82fc
JJ
725 span_err!(tcx.sess, pat.span, E0024,
726 "this pattern has {} field{}, but the corresponding {} has no fields",
727 subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name);
728
85aaf69f 729 for pat in subpats {
7453a54e 730 check_pat(pcx, &pat, tcx.types.err);
1a4d82fc
JJ
731 }
732 } else {
733 span_err!(tcx.sess, pat.span, E0023,
734 "this pattern has {} field{}, but the corresponding {} has {} field{}",
735 subpats.len(), if subpats.len() == 1 {""} else {"s"},
736 kind_name,
7453a54e 737 variant.fields.len(), if variant.fields.len() == 1 {""} else {"s"});
1a4d82fc 738
85aaf69f 739 for pat in subpats {
7453a54e 740 check_pat(pcx, &pat, tcx.types.err);
1a4d82fc
JJ
741 }
742 }
743 }
744}
745
746/// `path` is the AST path item naming the type of this struct.
747/// `fields` is the field patterns of the struct pattern.
748/// `struct_fields` describes the type of each field of the struct.
749/// `struct_id` is the ID of the struct.
750/// `etc` is true if the pattern said '...' and false otherwise.
751pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
752 span: Span,
e9174d1e
SL
753 fields: &'tcx [Spanned<hir::FieldPat>],
754 variant: ty::VariantDef<'tcx>,
755 substs: &Substs<'tcx>,
1a4d82fc
JJ
756 etc: bool) {
757 let tcx = pcx.fcx.ccx.tcx;
758
759 // Index the struct fields' types.
e9174d1e 760 let field_map = variant.fields
1a4d82fc 761 .iter()
e9174d1e 762 .map(|field| (field.name, field))
1a4d82fc
JJ
763 .collect::<FnvHashMap<_, _>>();
764
765 // Keep track of which fields have already appeared in the pattern.
85aaf69f 766 let mut used_fields = FnvHashMap();
1a4d82fc
JJ
767
768 // Typecheck each field.
85aaf69f 769 for &Spanned { node: ref field, span } in fields {
b039eaaf 770 let field_ty = match used_fields.entry(field.name) {
1a4d82fc 771 Occupied(occupied) => {
9cc50fc6
SL
772 let mut err = struct_span_err!(tcx.sess, span, E0025,
773 "field `{}` bound multiple times in the pattern",
774 field.name);
775 span_note!(&mut err, *occupied.get(),
776 "field `{}` previously bound here",
777 field.name);
778 err.emit();
1a4d82fc
JJ
779 tcx.types.err
780 }
781 Vacant(vacant) => {
782 vacant.insert(span);
b039eaaf 783 field_map.get(&field.name)
e9174d1e 784 .map(|f| pcx.fcx.field_ty(span, f, substs))
1a4d82fc
JJ
785 .unwrap_or_else(|| {
786 span_err!(tcx.sess, span, E0026,
787 "struct `{}` does not have a field named `{}`",
e9174d1e 788 tcx.item_path_str(variant.did),
b039eaaf 789 field.name);
1a4d82fc
JJ
790 tcx.types.err
791 })
792 }
793 };
794
7453a54e 795 check_pat(pcx, &field.pat, field_ty);
1a4d82fc
JJ
796 }
797
798 // Report an error if not all the fields were specified.
799 if !etc {
e9174d1e 800 for field in variant.fields
1a4d82fc
JJ
801 .iter()
802 .filter(|field| !used_fields.contains_key(&field.name)) {
803 span_err!(tcx.sess, span, E0027,
804 "pattern does not mention field `{}`",
c1a9b12d 805 field.name);
1a4d82fc
JJ
806 }
807 }
808}