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.
12 use middle
::infer
::{self, TypeOrigin}
;
13 use middle
::pat_util
::{PatIdMap, pat_id_map, pat_is_binding}
;
14 use middle
::pat_util
::pat_is_resolved_const
;
15 use middle
::privacy
::{AllPublic, LastMod}
;
16 use middle
::subst
::Substs
;
17 use middle
::ty
::{self, Ty, HasTypeFlags, LvaluePreference}
;
18 use check
::{check_expr, check_expr_has_type, check_expr_with_expectation}
;
19 use check
::{check_expr_coercable_to_type, demand, FnCtxt, Expectation}
;
20 use check
::{check_expr_with_lvalue_pref}
;
21 use check
::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type}
;
23 use require_same_types
;
24 use util
::nodemap
::FnvHashMap
;
28 use std
::collections
::hash_map
::Entry
::{Occupied, Vacant}
;
30 use syntax
::codemap
::{Span, Spanned}
;
34 use rustc_front
::print
::pprust
;
35 use rustc_front
::util
as hir_util
;
37 pub fn check_pat
<'a
, 'tcx
>(pcx
: &pat_ctxt
<'a
, 'tcx
>,
42 let tcx
= pcx
.fcx
.ccx
.tcx
;
44 debug
!("check_pat(pat={:?},expected={:?})",
50 fcx
.write_ty(pat
.id
, expected
);
52 hir
::PatLit(ref lt
) => {
53 check_expr(fcx
, &**lt
);
54 let expr_ty
= fcx
.expr_ty(&**lt
);
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
;
59 if let hir
::ExprLit(ref lt
) = lt
.node
{
60 if let ast
::LitByteStr(_
) = lt
.node
{
61 let expected_ty
= structurally_resolved_type(fcx
, pat
.span
, expected
);
62 if let ty
::TyRef(_
, mt
) = expected_ty
.sty
{
63 if let ty
::TySlice(_
) = mt
.ty
.sty
{
64 pat_ty
= tcx
.mk_imm_ref(tcx
.mk_region(ty
::ReStatic
),
65 tcx
.mk_slice(tcx
.types
.u8))
71 fcx
.write_ty(pat
.id
, pat_ty
);
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
82 // &'static str <: expected
84 // that's equivalent to there existing a LUB.
85 demand
::suptype(fcx
, pat
.span
, expected
, pat_ty
);
87 hir
::PatRange(ref begin
, ref end
) => {
88 check_expr(fcx
, begin
);
91 let lhs_ty
= fcx
.expr_ty(begin
);
92 let rhs_ty
= fcx
.expr_ty(end
);
94 // Check that both end-points are of numeric or char type.
95 let numeric_or_char
= |ty
: Ty
| ty
.is_numeric() || ty
.is_char();
96 let lhs_compat
= numeric_or_char(lhs_ty
);
97 let rhs_compat
= numeric_or_char(rhs_ty
);
99 if !lhs_compat
|| !rhs_compat
{
100 let span
= if !lhs_compat
&& !rhs_compat
{
102 } else if !lhs_compat
{
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
)
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()
124 // It's ok to return without a message as `require_same_types` prints an error.
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
);
133 fcx
.write_ty(pat
.id
, common_type
);
135 // subtyping doesn't matter here, as the value is some kind of scalar
136 demand
::eqtype(fcx
, pat
.span
, expected
, lhs_ty
);
138 hir
::PatEnum(..) | hir
::PatIdent(..)
139 if pat_is_resolved_const(&tcx
.def_map
.borrow(), pat
) => {
140 if let hir
::PatEnum(ref path
, ref subpats
) = pat
.node
{
141 if !(subpats
.is_some() && subpats
.as_ref().unwrap().is_empty()) {
142 bad_struct_kind_err(tcx
.sess
, pat
, path
, false);
146 let const_did
= tcx
.def_map
.borrow().get(&pat
.id
).unwrap().def_id();
147 let const_scheme
= tcx
.lookup_item_type(const_did
);
148 assert
!(const_scheme
.generics
.is_empty());
149 let const_ty
= pcx
.fcx
.instantiate_type_scheme(pat
.span
,
152 fcx
.write_ty(pat
.id
, const_ty
);
154 // FIXME(#20489) -- we should limit the types here to scalars or something!
156 // As with PatLit, what we really want here is that there
157 // exist a LUB, but for the cases that can occur, subtype
159 demand
::suptype(fcx
, pat
.span
, expected
, const_ty
);
161 hir
::PatIdent(bm
, ref path
, ref sub
) if pat_is_binding(&tcx
.def_map
.borrow(), pat
) => {
162 let typ
= fcx
.local_ty(pat
.span
, pat
.id
);
164 hir
::BindByRef(mutbl
) => {
165 // if the binding is like
166 // ref x | ref const x | ref mut x
167 // then `x` is assigned a value of type `&M T` where M is the mutability
168 // and T is the expected type.
169 let region_var
= fcx
.infcx().next_region_var(infer
::PatternRegion(pat
.span
));
170 let mt
= ty
::TypeAndMut { ty: expected, mutbl: mutbl }
;
171 let region_ty
= tcx
.mk_ref(tcx
.mk_region(region_var
), mt
);
173 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
174 // required. However, we use equality, which is stronger. See (*) for
176 demand
::eqtype(fcx
, pat
.span
, region_ty
, typ
);
178 // otherwise the type of x is the expected type T
179 hir
::BindByValue(_
) => {
180 // As above, `T <: typeof(x)` is required but we
181 // use equality, see (*) below.
182 demand
::eqtype(fcx
, pat
.span
, expected
, typ
);
186 fcx
.write_ty(pat
.id
, typ
);
188 // if there are multiple arms, make sure they all agree on
189 // what the type of the binding `x` ought to be
190 let canon_id
= *pcx
.map
.get(&path
.node
.name
).unwrap();
191 if canon_id
!= pat
.id
{
192 let ct
= fcx
.local_ty(pat
.span
, canon_id
);
193 demand
::eqtype(fcx
, pat
.span
, ct
, typ
);
196 if let Some(ref p
) = *sub
{
197 check_pat(pcx
, &**p
, expected
);
200 hir
::PatIdent(_
, ref path
, _
) => {
201 let path
= hir_util
::ident_to_path(path
.span
, path
.node
);
202 check_pat_enum(pcx
, pat
, &path
, Some(&[]), expected
, false);
204 hir
::PatEnum(ref path
, ref subpats
) => {
205 let subpats
= subpats
.as_ref().map(|v
| &v
[..]);
206 let is_tuple_struct_pat
= !(subpats
.is_some() && subpats
.unwrap().is_empty());
207 check_pat_enum(pcx
, pat
, path
, subpats
, expected
, is_tuple_struct_pat
);
209 hir
::PatQPath(ref qself
, ref path
) => {
210 let self_ty
= fcx
.to_ty(&qself
.ty
);
211 let path_res
= if let Some(&d
) = tcx
.def_map
.borrow().get(&pat
.id
) {
213 } else if qself
.position
== 0 {
214 // This is just a sentinel for finish_resolving_def_to_ty.
215 let sentinel
= fcx
.tcx().map
.local_def_id(ast
::CRATE_NODE_ID
);
216 def
::PathResolution
{
217 base_def
: def
::DefMod(sentinel
),
218 last_private
: LastMod(AllPublic
),
219 depth
: path
.segments
.len()
222 tcx
.sess
.span_bug(pat
.span
,
223 &format
!("unbound path {:?}", pat
))
225 if let Some((opt_ty
, segments
, def
)) =
226 resolve_ty_and_def_ufcs(fcx
, path_res
, Some(self_ty
),
227 path
, pat
.span
, pat
.id
) {
228 if check_assoc_item_is_const(pcx
, def
, pat
.span
) {
229 let scheme
= tcx
.lookup_item_type(def
.def_id());
230 let predicates
= tcx
.lookup_predicates(def
.def_id());
231 instantiate_path(fcx
, segments
,
233 opt_ty
, def
, pat
.span
, pat
.id
);
234 let const_ty
= fcx
.node_ty(pat
.id
);
235 demand
::suptype(fcx
, pat
.span
, expected
, const_ty
);
237 fcx
.write_error(pat
.id
)
241 hir
::PatStruct(ref path
, ref fields
, etc
) => {
242 check_pat_struct(pcx
, pat
, path
, fields
, etc
, expected
);
244 hir
::PatTup(ref elements
) => {
245 let element_tys
: Vec
<_
> =
246 (0..elements
.len()).map(|_
| fcx
.infcx().next_ty_var())
248 let pat_ty
= tcx
.mk_tup(element_tys
.clone());
249 fcx
.write_ty(pat
.id
, pat_ty
);
250 demand
::eqtype(fcx
, pat
.span
, expected
, pat_ty
);
251 for (element_pat
, element_ty
) in elements
.iter().zip(element_tys
) {
252 check_pat(pcx
, &**element_pat
, element_ty
);
255 hir
::PatBox(ref inner
) => {
256 let inner_ty
= fcx
.infcx().next_ty_var();
257 let uniq_ty
= tcx
.mk_box(inner_ty
);
259 if check_dereferencable(pcx
, pat
.span
, expected
, &**inner
) {
260 // Here, `demand::subtype` is good enough, but I don't
261 // think any errors can be introduced by using
263 demand
::eqtype(fcx
, pat
.span
, expected
, uniq_ty
);
264 fcx
.write_ty(pat
.id
, uniq_ty
);
265 check_pat(pcx
, &**inner
, inner_ty
);
267 fcx
.write_error(pat
.id
);
268 check_pat(pcx
, &**inner
, tcx
.types
.err
);
271 hir
::PatRegion(ref inner
, mutbl
) => {
272 let expected
= fcx
.infcx().shallow_resolve(expected
);
273 if check_dereferencable(pcx
, pat
.span
, expected
, &**inner
) {
274 // `demand::subtype` would be good enough, but using
275 // `eqtype` turns out to be equally general. See (*)
276 // below for details.
278 // Take region, inner-type from expected type if we
279 // can, to avoid creating needless variables. This
280 // also helps with the bad interactions of the given
281 // hack detailed in (*) below.
282 let (rptr_ty
, inner_ty
) = match expected
.sty
{
283 ty
::TyRef(_
, mt
) if mt
.mutbl
== mutbl
=> {
287 let inner_ty
= fcx
.infcx().next_ty_var();
288 let mt
= ty
::TypeAndMut { ty: inner_ty, mutbl: mutbl }
;
289 let region
= fcx
.infcx().next_region_var(infer
::PatternRegion(pat
.span
));
290 let rptr_ty
= tcx
.mk_ref(tcx
.mk_region(region
), mt
);
291 demand
::eqtype(fcx
, pat
.span
, expected
, rptr_ty
);
296 fcx
.write_ty(pat
.id
, rptr_ty
);
297 check_pat(pcx
, &**inner
, inner_ty
);
299 fcx
.write_error(pat
.id
);
300 check_pat(pcx
, &**inner
, tcx
.types
.err
);
303 hir
::PatVec(ref before
, ref slice
, ref after
) => {
304 let expected_ty
= structurally_resolved_type(fcx
, pat
.span
, expected
);
305 let inner_ty
= fcx
.infcx().next_ty_var();
306 let pat_ty
= match expected_ty
.sty
{
307 ty
::TyArray(_
, size
) => tcx
.mk_array(inner_ty
, {
308 let min_len
= before
.len() + after
.len();
310 Some(_
) => cmp
::max(min_len
, size
),
315 let region
= fcx
.infcx().next_region_var(infer
::PatternRegion(pat
.span
));
316 tcx
.mk_ref(tcx
.mk_region(region
), ty
::TypeAndMut
{
317 ty
: tcx
.mk_slice(inner_ty
),
318 mutbl
: expected_ty
.builtin_deref(true, ty
::NoPreference
).map(|mt
| mt
.mutbl
)
319 .unwrap_or(hir
::MutImmutable
)
324 fcx
.write_ty(pat
.id
, pat_ty
);
326 // `demand::subtype` would be good enough, but using
327 // `eqtype` turns out to be equally general. See (*)
328 // below for details.
329 demand
::eqtype(fcx
, pat
.span
, expected
, pat_ty
);
332 check_pat(pcx
, &**elt
, inner_ty
);
334 if let Some(ref slice
) = *slice
{
335 let region
= fcx
.infcx().next_region_var(infer
::PatternRegion(pat
.span
));
336 let mutbl
= expected_ty
.builtin_deref(true, ty
::NoPreference
)
337 .map_or(hir
::MutImmutable
, |mt
| mt
.mutbl
);
339 let slice_ty
= tcx
.mk_ref(tcx
.mk_region(region
), ty
::TypeAndMut
{
340 ty
: tcx
.mk_slice(inner_ty
),
343 check_pat(pcx
, &**slice
, slice_ty
);
346 check_pat(pcx
, &**elt
, inner_ty
);
352 // (*) In most of the cases above (literals and constants being
353 // the exception), we relate types using strict equality, evewn
354 // though subtyping would be sufficient. There are a few reasons
355 // for this, some of which are fairly subtle and which cost me
356 // (nmatsakis) an hour or two debugging to remember, so I thought
357 // I'd write them down this time.
359 // 1. There is no loss of expressiveness here, though it does
360 // cause some inconvenience. What we are saying is that the type
361 // of `x` becomes *exactly* what is expected. This can cause unnecessary
362 // errors in some cases, such as this one:
363 // it will cause errors in a case like this:
366 // fn foo<'x>(x: &'x int) {
373 // The reason we might get an error is that `z` might be
374 // assigned a type like `&'x int`, and then we would have
375 // a problem when we try to assign `&a` to `z`, because
376 // the lifetime of `&a` (i.e., the enclosing block) is
377 // shorter than `'x`.
379 // HOWEVER, this code works fine. The reason is that the
380 // expected type here is whatever type the user wrote, not
381 // the initializer's type. In this case the user wrote
382 // nothing, so we are going to create a type variable `Z`.
383 // Then we will assign the type of the initializer (`&'x
384 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
385 // will instantiate `Z` as a type `&'0 int` where `'0` is
386 // a fresh region variable, with the constraint that `'x :
387 // '0`. So basically we're all set.
389 // Note that there are two tests to check that this remains true
390 // (`regions-reassign-{match,let}-bound-pointer.rs`).
392 // 2. Things go horribly wrong if we use subtype. The reason for
393 // THIS is a fairly subtle case involving bound regions. See the
394 // `givens` field in `region_inference`, as well as the test
395 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
396 // for details. Short version is that we must sometimes detect
397 // relationships between specific region variables and regions
398 // bound in a closure signature, and that detection gets thrown
399 // off when we substitute fresh region variables here to enable
403 fn check_assoc_item_is_const(pcx
: &pat_ctxt
, def
: def
::Def
, span
: Span
) -> bool
{
405 def
::DefAssociatedConst(..) => true,
406 def
::DefMethod(..) => {
407 span_err
!(pcx
.fcx
.ccx
.tcx
.sess
, span
, E0327
,
408 "associated items in match patterns must be constants");
412 pcx
.fcx
.ccx
.tcx
.sess
.span_bug(span
, "non-associated item in
413 check_assoc_item_is_const");
418 pub fn check_dereferencable
<'a
, 'tcx
>(pcx
: &pat_ctxt
<'a
, 'tcx
>,
419 span
: Span
, expected
: Ty
<'tcx
>,
420 inner
: &hir
::Pat
) -> bool
{
422 let tcx
= pcx
.fcx
.ccx
.tcx
;
423 if pat_is_binding(&tcx
.def_map
.borrow(), inner
) {
424 let expected
= fcx
.infcx().shallow_resolve(expected
);
425 expected
.builtin_deref(true, ty
::NoPreference
).map_or(true, |mt
| match mt
.ty
.sty
{
427 // This is "x = SomeTrait" being reduced from
428 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
429 span_err
!(tcx
.sess
, span
, E0033
,
430 "type `{}` cannot be dereferenced",
431 fcx
.infcx().ty_to_string(expected
));
441 pub fn check_match
<'a
, 'tcx
>(fcx
: &FnCtxt
<'a
, 'tcx
>,
442 expr
: &'tcx hir
::Expr
,
443 discrim
: &'tcx hir
::Expr
,
444 arms
: &'tcx
[hir
::Arm
],
445 expected
: Expectation
<'tcx
>,
446 match_src
: hir
::MatchSource
) {
447 let tcx
= fcx
.ccx
.tcx
;
449 // Not entirely obvious: if matches may create ref bindings, we
450 // want to use the *precise* type of the discriminant, *not* some
451 // supertype, as the "discriminant type" (issue #23116).
452 let contains_ref_bindings
= arms
.iter()
453 .filter_map(|a
| tcx
.arm_contains_ref_binding(a
))
454 .max_by_key(|m
| match *m
{
455 hir
::MutMutable
=> 1,
456 hir
::MutImmutable
=> 0,
459 if let Some(m
) = contains_ref_bindings
{
460 check_expr_with_lvalue_pref(fcx
, discrim
, LvaluePreference
::from_mutbl(m
));
461 discrim_ty
= fcx
.expr_ty(discrim
);
463 // ...but otherwise we want to use any supertype of the
464 // discriminant. This is sort of a workaround, see note (*) in
465 // `check_pat` for some details.
466 discrim_ty
= fcx
.infcx().next_ty_var();
467 check_expr_has_type(fcx
, discrim
, discrim_ty
);
470 // Typecheck the patterns first, so that we get types for all the
473 let mut pcx
= pat_ctxt
{
475 map
: pat_id_map(&tcx
.def_map
, &*arm
.pats
[0]),
478 check_pat(&mut pcx
, &**p
, discrim_ty
);
482 // Now typecheck the blocks.
484 // The result of the match is the common supertype of all the
485 // arms. Start out the value as bottom, since it's the, well,
486 // bottom the type lattice, and we'll be moving up the lattice as
487 // we process each arm. (Note that any match with 0 arms is matching
488 // on any empty type and is therefore unreachable; should the flow
489 // of execution reach it, we will panic, so bottom is an appropriate
490 // type in that case)
491 let expected
= expected
.adjust_for_branches(fcx
);
492 let result_ty
= arms
.iter().fold(fcx
.infcx().next_diverging_ty_var(), |result_ty
, arm
| {
493 let bty
= match expected
{
494 // We don't coerce to `()` so that if the match expression is a
495 // statement it's branches can have any consistent type. That allows
496 // us to give better error messages (pointing to a usually better
497 // arm for inconsistent arms or to the whole match when a `()` type
499 Expectation
::ExpectHasType(ety
) if ety
!= fcx
.tcx().mk_nil() => {
500 check_expr_coercable_to_type(fcx
, &*arm
.body
, ety
);
504 check_expr_with_expectation(fcx
, &*arm
.body
, expected
);
505 fcx
.node_ty(arm
.body
.id
)
509 if let Some(ref e
) = arm
.guard
{
510 check_expr_has_type(fcx
, &**e
, tcx
.types
.bool
);
513 if result_ty
.references_error() || bty
.references_error() {
516 let (origin
, expected
, found
) = match match_src
{
517 /* if-let construct without an else block */
518 hir
::MatchSource
::IfLetDesugar { contains_else_clause }
519 if !contains_else_clause
=> (
520 TypeOrigin
::IfExpressionWithNoElse(expr
.span
),
525 TypeOrigin
::MatchExpressionArm(expr
.span
, arm
.body
.span
, match_src
),
531 infer
::common_supertype(
541 fcx
.write_ty(expr
.id
, result_ty
);
544 pub struct pat_ctxt
<'a
, 'tcx
: 'a
> {
545 pub fcx
: &'a FnCtxt
<'a
, 'tcx
>,
549 pub fn check_pat_struct
<'a
, 'tcx
>(pcx
: &pat_ctxt
<'a
, 'tcx
>, pat
: &'tcx hir
::Pat
,
550 path
: &hir
::Path
, fields
: &'tcx
[Spanned
<hir
::FieldPat
>],
551 etc
: bool
, expected
: Ty
<'tcx
>) {
553 let tcx
= pcx
.fcx
.ccx
.tcx
;
555 let def
= tcx
.def_map
.borrow().get(&pat
.id
).unwrap().full_def();
556 let variant
= match fcx
.def_struct_variant(def
, path
.span
) {
557 Some((_
, variant
)) => variant
,
559 let name
= pprust
::path_to_string(path
);
560 span_err
!(tcx
.sess
, pat
.span
, E0163
,
561 "`{}` does not name a struct or a struct variant", name
);
562 fcx
.write_error(pat
.id
);
564 for field
in fields
{
565 check_pat(pcx
, &field
.node
.pat
, tcx
.types
.err
);
571 let pat_ty
= pcx
.fcx
.instantiate_type(def
.def_id(), path
);
572 let item_substs
= match pat_ty
.sty
{
573 ty
::TyStruct(_
, substs
) | ty
::TyEnum(_
, substs
) => substs
,
574 _
=> tcx
.sess
.span_bug(pat
.span
, "struct variant is not an ADT")
576 demand
::eqtype(fcx
, pat
.span
, expected
, pat_ty
);
577 check_struct_pat_fields(pcx
, pat
.span
, fields
, variant
, &item_substs
, etc
);
579 fcx
.write_ty(pat
.id
, pat_ty
);
580 fcx
.write_substs(pat
.id
, ty
::ItemSubsts { substs: item_substs.clone() }
);
583 // This function exists due to the warning "diagnostic code E0164 already used"
584 fn bad_struct_kind_err(sess
: &Session
, pat
: &hir
::Pat
, path
: &hir
::Path
, lint
: bool
) {
585 let name
= pprust
::path_to_string(path
);
586 let msg
= format
!("`{}` does not name a tuple variant or a tuple struct", name
);
589 format
!("{}; RFC 218 disallowed matching of unit variants or unit structs via {}(..)",
592 sess
.add_lint(lint
::builtin
::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT
,
597 span_err
!(sess
, pat
.span
, E0164
, "{}", msg
);
601 pub fn check_pat_enum
<'a
, 'tcx
>(pcx
: &pat_ctxt
<'a
, 'tcx
>,
604 subpats
: Option
<&'tcx
[P
<hir
::Pat
>]>,
606 is_tuple_struct_pat
: bool
)
608 // Typecheck the path.
610 let tcx
= pcx
.fcx
.ccx
.tcx
;
612 let path_res
= *tcx
.def_map
.borrow().get(&pat
.id
).unwrap();
614 let (opt_ty
, segments
, def
) = match resolve_ty_and_def_ufcs(fcx
, path_res
,
617 Some(resolution
) => resolution
,
618 // Error handling done inside resolve_ty_and_def_ufcs, so if
619 // resolution fails just return.
623 // Items that were partially resolved before should have been resolved to
624 // associated constants (i.e. not methods).
625 if path_res
.depth
!= 0 && !check_assoc_item_is_const(pcx
, def
, pat
.span
) {
626 fcx
.write_error(pat
.id
);
630 let enum_def
= def
.variant_def_ids()
631 .map_or_else(|| def
.def_id(), |(enum_def
, _
)| enum_def
);
633 let ctor_scheme
= tcx
.lookup_item_type(enum_def
);
634 let ctor_predicates
= tcx
.lookup_predicates(enum_def
);
635 let path_scheme
= if ctor_scheme
.ty
.is_fn() {
636 let fn_ret
= tcx
.no_late_bound_regions(&ctor_scheme
.ty
.fn_ret()).unwrap();
639 generics
: ctor_scheme
.generics
,
644 instantiate_path(pcx
.fcx
, segments
,
645 path_scheme
, &ctor_predicates
,
646 opt_ty
, def
, pat
.span
, pat
.id
);
648 let report_bad_struct_kind
= |is_warning
| {
649 bad_struct_kind_err(tcx
.sess
, pat
, path
, is_warning
);
650 if is_warning { return; }
651 fcx
.write_error(pat
.id
);
652 if let Some(subpats
) = subpats
{
654 check_pat(pcx
, &**pat
, tcx
.types
.err
);
659 // If we didn't have a fully resolved path to start with, we had an
660 // associated const, and we should quit now, since the rest of this
661 // function uses checks specific to structs and enums.
662 if path_res
.depth
!= 0 {
663 if is_tuple_struct_pat
{
664 report_bad_struct_kind(false);
666 let pat_ty
= fcx
.node_ty(pat
.id
);
667 demand
::suptype(fcx
, pat
.span
, expected
, pat_ty
);
672 let pat_ty
= fcx
.node_ty(pat
.id
);
673 demand
::eqtype(fcx
, pat
.span
, expected
, pat_ty
);
675 let real_path_ty
= fcx
.node_ty(pat
.id
);
676 let (arg_tys
, kind_name
): (Vec
<_
>, &'
static str) = match real_path_ty
.sty
{
677 ty
::TyEnum(enum_def
, expected_substs
)
678 if def
== def
::DefVariant(enum_def
.did
, def
.def_id(), false) =>
680 let variant
= enum_def
.variant_of_def(def
);
681 if is_tuple_struct_pat
&& variant
.kind() != ty
::VariantKind
::Tuple
{
682 // Matching unit variants with tuple variant patterns (`UnitVariant(..)`)
683 // is allowed for backward compatibility.
684 let is_special_case
= variant
.kind() == ty
::VariantKind
::Unit
;
685 report_bad_struct_kind(is_special_case
);
686 if !is_special_case
{
692 .map(|f
| fcx
.instantiate_type_scheme(pat
.span
,
698 ty
::TyStruct(struct_def
, expected_substs
) => {
699 let variant
= struct_def
.struct_variant();
700 if is_tuple_struct_pat
&& variant
.kind() != ty
::VariantKind
::Tuple
{
701 // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
702 // is allowed for backward compatibility.
703 let is_special_case
= variant
.kind() == ty
::VariantKind
::Unit
;
704 report_bad_struct_kind(is_special_case
);
709 .map(|f
| fcx
.instantiate_type_scheme(pat
.span
,
716 report_bad_struct_kind(false);
721 if let Some(subpats
) = subpats
{
722 if subpats
.len() == arg_tys
.len() {
723 for (subpat
, arg_ty
) in subpats
.iter().zip(arg_tys
) {
724 check_pat(pcx
, &**subpat
, arg_ty
);
726 } else if arg_tys
.is_empty() {
727 span_err
!(tcx
.sess
, pat
.span
, E0024
,
728 "this pattern has {} field{}, but the corresponding {} has no fields",
729 subpats
.len(), if subpats
.len() == 1 {""}
else {"s"}
, kind_name
);
732 check_pat(pcx
, &**pat
, tcx
.types
.err
);
735 span_err
!(tcx
.sess
, pat
.span
, E0023
,
736 "this pattern has {} field{}, but the corresponding {} has {} field{}",
737 subpats
.len(), if subpats
.len() == 1 {""}
else {"s"}
,
739 arg_tys
.len(), if arg_tys
.len() == 1 {""}
else {"s"}
);
742 check_pat(pcx
, &**pat
, tcx
.types
.err
);
748 /// `path` is the AST path item naming the type of this struct.
749 /// `fields` is the field patterns of the struct pattern.
750 /// `struct_fields` describes the type of each field of the struct.
751 /// `struct_id` is the ID of the struct.
752 /// `etc` is true if the pattern said '...' and false otherwise.
753 pub fn check_struct_pat_fields
<'a
, 'tcx
>(pcx
: &pat_ctxt
<'a
, 'tcx
>,
755 fields
: &'tcx
[Spanned
<hir
::FieldPat
>],
756 variant
: ty
::VariantDef
<'tcx
>,
757 substs
: &Substs
<'tcx
>,
759 let tcx
= pcx
.fcx
.ccx
.tcx
;
761 // Index the struct fields' types.
762 let field_map
= variant
.fields
764 .map(|field
| (field
.name
, field
))
765 .collect
::<FnvHashMap
<_
, _
>>();
767 // Keep track of which fields have already appeared in the pattern.
768 let mut used_fields
= FnvHashMap();
770 // Typecheck each field.
771 for &Spanned { node: ref field, span }
in fields
{
772 let field_ty
= match used_fields
.entry(field
.name
) {
773 Occupied(occupied
) => {
774 span_err
!(tcx
.sess
, span
, E0025
,
775 "field `{}` bound multiple times in the pattern",
777 span_note
!(tcx
.sess
, *occupied
.get(),
778 "field `{}` previously bound here",
784 field_map
.get(&field
.name
)
785 .map(|f
| pcx
.fcx
.field_ty(span
, f
, substs
))
787 span_err
!(tcx
.sess
, span
, E0026
,
788 "struct `{}` does not have a field named `{}`",
789 tcx
.item_path_str(variant
.did
),
796 check_pat(pcx
, &*field
.pat
, field_ty
);
799 // Report an error if not all the fields were specified.
801 for field
in variant
.fields
803 .filter(|field
| !used_fields
.contains_key(&field
.name
)) {
804 span_err
!(tcx
.sess
, span
, E0027
,
805 "pattern does not mention field `{}`",