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.
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.
13 use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const};
14 use middle::subst::{Substs};
15 use middle::ty::{self, Ty};
16 use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
17 use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
18 use check::{instantiate_path, structurally_resolved_type, valid_range_bounds};
19 use require_same_types;
20 use util::nodemap::FnvHashMap;
21 use util::ppaux::Repr;
24 use std::collections::hash_map::Entry::{Occupied, Vacant};
27 use syntax::codemap::{Span, Spanned};
28 use syntax::parse::token;
29 use syntax::print::pprust;
32 pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
37 let tcx = pcx.fcx.ccx.tcx;
39 debug!("check_pat(pat={},expected={})",
45 fcx.write_ty(pat.id, expected);
47 ast::PatLit(ref lt) => {
48 check_expr(fcx, &**lt);
49 let expr_ty = fcx.expr_ty(&**lt);
50 fcx.write_ty(pat.id, expr_ty);
52 // somewhat surprising: in this case, the subtyping
53 // relation goes the opposite way as the other
54 // cases. Actually what we really want is not a subtyping
55 // relation at all but rather that there exists a LUB (so
56 // that they can be compared). However, in practice,
57 // constants are always scalars or strings. For scalars
58 // subtyping is irrelevant, and for strings `expr_ty` is
59 // type is `&'static str`, so if we say that
61 // &'static str <: expected
63 // that's equivalent to there existing a LUB.
64 demand::suptype(fcx, pat.span, expected, expr_ty);
66 ast::PatRange(ref begin, ref end) => {
67 check_expr(fcx, &**begin);
68 check_expr(fcx, &**end);
70 let lhs_ty = fcx.expr_ty(&**begin);
71 let rhs_ty = fcx.expr_ty(&**end);
75 tcx, Some(fcx.infcx()), false, pat.span, lhs_ty, rhs_ty,
76 || "mismatched types in range".to_string());
79 lhs_eq_rhs && (ty::type_is_numeric(lhs_ty) || ty::type_is_char(lhs_ty));
82 match valid_range_bounds(fcx.ccx, &**begin, &**end) {
84 span_err!(tcx.sess, begin.span, E0030,
85 "lower range bound must be less than upper");
88 span_err!(tcx.sess, begin.span, E0031,
89 "mismatched types in range");
94 span_err!(tcx.sess, begin.span, E0029,
95 "only char and numeric types are allowed in range");
98 fcx.write_ty(pat.id, lhs_ty);
100 // subtyping doesn't matter here, as the value is some kind of scalar
101 demand::eqtype(fcx, pat.span, expected, lhs_ty);
103 ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
104 let const_did = tcx.def_map.borrow()[pat.id].clone().def_id();
105 let const_scheme = ty::lookup_item_type(tcx, const_did);
106 assert!(const_scheme.generics.is_empty());
107 let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
110 fcx.write_ty(pat.id, const_ty);
112 // FIXME(#20489) -- we should limit the types here to scalars or something!
114 // As with PatLit, what we really want here is that there
115 // exist a LUB, but for the cases that can occur, subtype
117 demand::suptype(fcx, pat.span, expected, const_ty);
119 ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
120 let typ = fcx.local_ty(pat.span, pat.id);
122 ast::BindByRef(mutbl) => {
123 // if the binding is like
124 // ref x | ref const x | ref mut x
125 // then `x` is assigned a value of type `&M T` where M is the mutability
126 // and T is the expected type.
127 let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
128 let mt = ty::mt { ty: expected, mutbl: mutbl };
129 let region_ty = ty::mk_rptr(tcx, tcx.mk_region(region_var), mt);
131 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
132 // required. However, we use equality, which is stronger. See (*) for
134 demand::eqtype(fcx, pat.span, region_ty, typ);
136 // otherwise the type of x is the expected type T
137 ast::BindByValue(_) => {
138 // As above, `T <: typeof(x)` is required but we
139 // use equality, see (*) below.
140 demand::eqtype(fcx, pat.span, expected, typ);
144 fcx.write_ty(pat.id, typ);
146 // if there are multiple arms, make sure they all agree on
147 // what the type of the binding `x` ought to be
148 let canon_id = pcx.map[path.node];
149 if canon_id != pat.id {
150 let ct = fcx.local_ty(pat.span, canon_id);
151 demand::eqtype(fcx, pat.span, ct, typ);
154 if let Some(ref p) = *sub {
155 check_pat(pcx, &**p, expected);
158 ast::PatIdent(_, ref path, _) => {
159 let path = ast_util::ident_to_path(path.span, path.node);
160 check_pat_enum(pcx, pat, &path, &Some(vec![]), expected);
162 ast::PatEnum(ref path, ref subpats) => {
163 check_pat_enum(pcx, pat, path, subpats, expected);
165 ast::PatStruct(ref path, ref fields, etc) => {
166 check_pat_struct(pcx, pat, path, fields.as_slice(), etc, expected);
168 ast::PatTup(ref elements) => {
169 let element_tys: Vec<_> =
170 range(0, elements.len()).map(|_| fcx.infcx().next_ty_var())
172 let pat_ty = ty::mk_tup(tcx, element_tys.clone());
173 fcx.write_ty(pat.id, pat_ty);
174 demand::eqtype(fcx, pat.span, expected, pat_ty);
175 for (element_pat, element_ty) in elements.iter().zip(element_tys.into_iter()) {
176 check_pat(pcx, &**element_pat, element_ty);
179 ast::PatBox(ref inner) => {
180 let inner_ty = fcx.infcx().next_ty_var();
181 let uniq_ty = ty::mk_uniq(tcx, inner_ty);
183 if check_dereferencable(pcx, pat.span, expected, &**inner) {
184 // Here, `demand::subtype` is good enough, but I don't
185 // think any errors can be introduced by using
187 demand::eqtype(fcx, pat.span, expected, uniq_ty);
188 fcx.write_ty(pat.id, uniq_ty);
189 check_pat(pcx, &**inner, inner_ty);
191 fcx.write_error(pat.id);
192 check_pat(pcx, &**inner, tcx.types.err);
195 ast::PatRegion(ref inner, mutbl) => {
196 let inner_ty = fcx.infcx().next_ty_var();
198 let mt = ty::mt { ty: inner_ty, mutbl: mutbl };
199 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
200 let rptr_ty = ty::mk_rptr(tcx, tcx.mk_region(region), mt);
202 if check_dereferencable(pcx, pat.span, expected, &**inner) {
203 // `demand::subtype` would be good enough, but using
204 // `eqtype` turns out to be equally general. See (*)
205 // below for details.
206 demand::eqtype(fcx, pat.span, expected, rptr_ty);
207 fcx.write_ty(pat.id, rptr_ty);
208 check_pat(pcx, &**inner, inner_ty);
210 fcx.write_error(pat.id);
211 check_pat(pcx, &**inner, tcx.types.err);
214 ast::PatVec(ref before, ref slice, ref after) => {
215 let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
216 let inner_ty = fcx.infcx().next_ty_var();
217 let pat_ty = match expected_ty.sty {
218 ty::ty_vec(_, Some(size)) => ty::mk_vec(tcx, inner_ty, Some({
219 let min_len = before.len() + after.len();
221 Some(_) => cmp::max(min_len, size),
226 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
227 ty::mk_slice(tcx, tcx.mk_region(region), ty::mt {
229 mutbl: ty::deref(expected_ty, true).map(|mt| mt.mutbl)
230 .unwrap_or(ast::MutImmutable)
235 fcx.write_ty(pat.id, pat_ty);
237 // `demand::subtype` would be good enough, but using
238 // `eqtype` turns out to be equally general. See (*)
239 // below for details.
240 demand::eqtype(fcx, pat.span, expected, pat_ty);
242 for elt in before.iter() {
243 check_pat(pcx, &**elt, inner_ty);
245 if let Some(ref slice) = *slice {
246 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
247 let mutbl = ty::deref(expected_ty, true)
248 .map_or(ast::MutImmutable, |mt| mt.mutbl);
250 let slice_ty = ty::mk_slice(tcx, tcx.mk_region(region), ty::mt {
254 check_pat(pcx, &**slice, slice_ty);
256 for elt in after.iter() {
257 check_pat(pcx, &**elt, inner_ty);
260 ast::PatMac(_) => tcx.sess.bug("unexpanded macro")
264 // (*) In most of the cases above (literals and constants being
265 // the exception), we relate types using strict equality, evewn
266 // though subtyping would be sufficient. There are a few reasons
267 // for this, some of which are fairly subtle and which cost me
268 // (nmatsakis) an hour or two debugging to remember, so I thought
269 // I'd write them down this time.
271 // 1. Most importantly, there is no loss of expressiveness
272 // here. What we are saying is that the type of `x`
273 // becomes *exactly* what is expected. This might seem
274 // like it will cause errors in a case like this:
277 // fn foo<'x>(x: &'x int) {
284 // The reason we might get an error is that `z` might be
285 // assigned a type like `&'x int`, and then we would have
286 // a problem when we try to assign `&a` to `z`, because
287 // the lifetime of `&a` (i.e., the enclosing block) is
288 // shorter than `'x`.
290 // HOWEVER, this code works fine. The reason is that the
291 // expected type here is whatever type the user wrote, not
292 // the initializer's type. In this case the user wrote
293 // nothing, so we are going to create a type variable `Z`.
294 // Then we will assign the type of the initializer (`&'x
295 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
296 // will instantiate `Z` as a type `&'0 int` where `'0` is
297 // a fresh region variable, with the constraint that `'x :
298 // '0`. So basically we're all set.
300 // Note that there are two tests to check that this remains true
301 // (`regions-reassign-{match,let}-bound-pointer.rs`).
303 // 2. Things go horribly wrong if we use subtype. The reason for
304 // THIS is a fairly subtle case involving bound regions. See the
305 // `givens` field in `region_inference`, as well as the test
306 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
307 // for details. Short version is that we must sometimes detect
308 // relationships between specific region variables and regions
309 // bound in a closure signature, and that detection gets thrown
310 // off when we substitute fresh region variables here to enable
314 pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
315 span: Span, expected: Ty<'tcx>,
316 inner: &ast::Pat) -> bool {
318 let tcx = pcx.fcx.ccx.tcx;
319 if pat_is_binding(&tcx.def_map, inner) {
320 let expected = fcx.infcx().shallow_resolve(expected);
321 ty::deref(expected, true).map_or(true, |mt| match mt.ty.sty {
323 // This is "x = SomeTrait" being reduced from
324 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
325 span_err!(tcx.sess, span, E0033,
326 "type `{}` cannot be dereferenced",
327 fcx.infcx().ty_to_string(expected));
337 pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
341 expected: Expectation<'tcx>,
342 match_src: ast::MatchSource) {
343 let tcx = fcx.ccx.tcx;
345 let discrim_ty = fcx.infcx().next_ty_var();
346 check_expr_has_type(fcx, discrim, discrim_ty);
348 // Typecheck the patterns first, so that we get types for all the
350 for arm in arms.iter() {
351 let mut pcx = pat_ctxt {
353 map: pat_id_map(&tcx.def_map, &*arm.pats[0]),
355 for p in arm.pats.iter() {
356 check_pat(&mut pcx, &**p, discrim_ty);
360 // Now typecheck the blocks.
362 // The result of the match is the common supertype of all the
363 // arms. Start out the value as bottom, since it's the, well,
364 // bottom the type lattice, and we'll be moving up the lattice as
365 // we process each arm. (Note that any match with 0 arms is matching
366 // on any empty type and is therefore unreachable; should the flow
367 // of execution reach it, we will panic, so bottom is an appropriate
368 // type in that case)
369 let expected = expected.adjust_for_branches(fcx);
370 let result_ty = arms.iter().fold(fcx.infcx().next_diverging_ty_var(), |result_ty, arm| {
371 let bty = match expected {
372 // We don't coerce to `()` so that if the match expression is a
373 // statement it's branches can have any consistent type. That allows
374 // us to give better error messages (pointing to a usually better
375 // arm for inconsistent arms or to the whole match when a `()` type
377 Expectation::ExpectHasType(ety) if ety != ty::mk_nil(fcx.tcx()) => {
378 check_expr_coercable_to_type(fcx, &*arm.body, ety);
382 check_expr_with_expectation(fcx, &*arm.body, expected);
383 fcx.node_ty(arm.body.id)
387 if let Some(ref e) = arm.guard {
388 check_expr_has_type(fcx, &**e, tcx.types.bool);
391 if ty::type_is_error(result_ty) || ty::type_is_error(bty) {
394 let (origin, expected, found) = match match_src {
395 /* if-let construct without an else block */
396 ast::MatchSource::IfLetDesugar { contains_else_clause }
397 if !contains_else_clause => (
398 infer::IfExpressionWithNoElse(expr.span),
403 infer::MatchExpressionArm(expr.span, arm.body.span),
409 infer::common_supertype(
419 fcx.write_ty(expr.id, result_ty);
422 pub struct pat_ctxt<'a, 'tcx: 'a> {
423 pub fcx: &'a FnCtxt<'a, 'tcx>,
427 pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
428 path: &ast::Path, fields: &[Spanned<ast::FieldPat>],
429 etc: bool, expected: Ty<'tcx>) {
431 let tcx = pcx.fcx.ccx.tcx;
433 let def = tcx.def_map.borrow()[pat.id].clone();
434 let (enum_def_id, variant_def_id) = match def {
435 def::DefTrait(_) => {
436 let name = pprust::path_to_string(path);
437 span_err!(tcx.sess, pat.span, E0168,
438 "use of trait `{}` in a struct pattern", name);
439 fcx.write_error(pat.id);
441 for field in fields.iter() {
442 check_pat(pcx, &*field.node.pat, tcx.types.err);
447 let def_type = ty::lookup_item_type(tcx, def.def_id());
448 match def_type.ty.sty {
449 ty::ty_struct(struct_def_id, _) =>
450 (struct_def_id, struct_def_id),
451 ty::ty_enum(enum_def_id, _)
452 if def == def::DefVariant(enum_def_id, def.def_id(), true) =>
453 (enum_def_id, def.def_id()),
455 let name = pprust::path_to_string(path);
456 span_err!(tcx.sess, pat.span, E0163,
457 "`{}` does not name a struct or a struct variant", name);
458 fcx.write_error(pat.id);
460 for field in fields.iter() {
461 check_pat(pcx, &*field.node.pat, tcx.types.err);
469 instantiate_path(pcx.fcx, path, ty::lookup_item_type(tcx, enum_def_id),
470 def, pat.span, pat.id);
472 let pat_ty = fcx.node_ty(pat.id);
473 demand::eqtype(fcx, pat.span, expected, pat_ty);
475 let item_substs = fcx
478 .map(|substs| substs.substs.clone())
479 .unwrap_or_else(|| Substs::empty());
481 let struct_fields = ty::struct_fields(tcx, variant_def_id, &item_substs);
482 check_struct_pat_fields(pcx, pat.span, fields, struct_fields.as_slice(),
483 variant_def_id, etc);
486 pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
487 path: &ast::Path, subpats: &Option<Vec<P<ast::Pat>>>,
488 expected: Ty<'tcx>) {
490 // Typecheck the path.
492 let tcx = pcx.fcx.ccx.tcx;
494 let def = tcx.def_map.borrow()[pat.id].clone();
495 let enum_def = def.variant_def_ids()
496 .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
498 let ctor_scheme = ty::lookup_item_type(tcx, enum_def);
499 let path_scheme = if ty::is_fn_ty(ctor_scheme.ty) {
500 let fn_ret = ty::assert_no_late_bound_regions(tcx, &ty::ty_fn_ret(ctor_scheme.ty));
503 generics: ctor_scheme.generics,
508 instantiate_path(pcx.fcx, path, path_scheme, def, pat.span, pat.id);
510 let pat_ty = fcx.node_ty(pat.id);
511 demand::eqtype(fcx, pat.span, expected, pat_ty);
513 let real_path_ty = fcx.node_ty(pat.id);
514 let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
515 ty::ty_enum(enum_def_id, expected_substs)
516 if def == def::DefVariant(enum_def_id, def.def_id(), false) =>
518 let variant = ty::enum_variant_with_id(tcx, enum_def_id, def.def_id());
520 .map(|t| fcx.instantiate_type_scheme(pat.span, expected_substs, t))
524 ty::ty_struct(struct_def_id, expected_substs) => {
525 let struct_fields = ty::struct_fields(tcx, struct_def_id, expected_substs);
526 (struct_fields.iter()
527 .map(|field| fcx.instantiate_type_scheme(pat.span,
534 let name = pprust::path_to_string(path);
535 span_err!(tcx.sess, pat.span, E0164,
536 "`{}` does not name a non-struct variant or a tuple struct", name);
537 fcx.write_error(pat.id);
539 if let Some(ref subpats) = *subpats {
540 for pat in subpats.iter() {
541 check_pat(pcx, &**pat, tcx.types.err);
548 if let Some(ref subpats) = *subpats {
549 if subpats.len() == arg_tys.len() {
550 for (subpat, arg_ty) in subpats.iter().zip(arg_tys.iter()) {
551 check_pat(pcx, &**subpat, *arg_ty);
553 } else if arg_tys.len() == 0 {
554 span_err!(tcx.sess, pat.span, E0024,
555 "this pattern has {} field{}, but the corresponding {} has no fields",
556 subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name);
558 for pat in subpats.iter() {
559 check_pat(pcx, &**pat, tcx.types.err);
562 span_err!(tcx.sess, pat.span, E0023,
563 "this pattern has {} field{}, but the corresponding {} has {} field{}",
564 subpats.len(), if subpats.len() == 1 {""} else {"s"},
566 arg_tys.len(), if arg_tys.len() == 1 {""} else {"s"});
568 for pat in subpats.iter() {
569 check_pat(pcx, &**pat, tcx.types.err);
575 /// `path` is the AST path item naming the type of this struct.
576 /// `fields` is the field patterns of the struct pattern.
577 /// `struct_fields` describes the type of each field of the struct.
578 /// `struct_id` is the ID of the struct.
579 /// `etc` is true if the pattern said '...' and false otherwise.
580 pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
582 fields: &[Spanned<ast::FieldPat>],
583 struct_fields: &[ty::field<'tcx>],
584 struct_id: ast::DefId,
586 let tcx = pcx.fcx.ccx.tcx;
588 // Index the struct fields' types.
589 let field_type_map = struct_fields
591 .map(|field| (field.name, field.mt.ty))
592 .collect::<FnvHashMap<_, _>>();
594 // Keep track of which fields have already appeared in the pattern.
595 let mut used_fields = FnvHashMap::new();
597 // Typecheck each field.
598 for &Spanned { node: ref field, span } in fields.iter() {
599 let field_type = match used_fields.entry(field.ident.name) {
600 Occupied(occupied) => {
601 span_err!(tcx.sess, span, E0025,
602 "field `{}` bound multiple times in the pattern",
603 token::get_ident(field.ident));
604 span_note!(tcx.sess, *occupied.get(),
605 "field `{}` previously bound here",
606 token::get_ident(field.ident));
611 field_type_map.get(&field.ident.name).cloned()
613 span_err!(tcx.sess, span, E0026,
614 "struct `{}` does not have a field named `{}`",
615 ty::item_path_str(tcx, struct_id),
616 token::get_ident(field.ident));
622 let field_type = pcx.fcx.normalize_associated_types_in(span, &field_type);
624 check_pat(pcx, &*field.pat, field_type);
627 // Report an error if not all the fields were specified.
629 for field in struct_fields
631 .filter(|field| !used_fields.contains_key(&field.name)) {
632 span_err!(tcx.sess, span, E0027,
633 "pattern does not mention field `{}`",
634 token::get_name(field.name));