1 // Copyright 2012 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
11
12 use middle::resolve;
13
14 use collections::HashMap;
15 use syntax::ast::*;
16 use syntax::ast_util::{path_to_ident, walk_pat};
17 use syntax::codemap::Span;
18
19 pub type PatIdMap = HashMap<Ident, NodeId>;
20
21 // This is used because same-named variables in alternative patterns need to
22 // use the NodeId of their namesake in the first pattern.
23 pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap {
24 let mut map = HashMap::new();
25 pat_bindings(dm, pat, |_bm, p_id, _s, n| {
26 map.insert(path_to_ident(n), p_id);
27 });
28 map
29 }
30
31 pub fn pat_is_variant_or_struct(dm: &resolve::DefMap, pat: &Pat) -> bool {
32 match pat.node {
33 PatEnum(_, _) | PatIdent(_, _, None) | PatStruct(..) => {
34 match dm.borrow().find(&pat.id) {
35 Some(&DefVariant(..)) | Some(&DefStruct(..)) => true,
36 _ => false
37 }
38 }
39 _ => false
40 }
41 }
42
43 pub fn pat_is_const(dm: &resolve::DefMap, pat: &Pat) -> bool {
44 match pat.node {
45 PatIdent(_, _, None) | PatEnum(..) => {
46 match dm.borrow().find(&pat.id) {
47 Some(&DefStatic(_, false)) => true,
48 _ => false
49 }
50 }
51 _ => false
52 }
53 }
54
55 pub fn pat_is_binding(dm: &resolve::DefMap, pat: &Pat) -> bool {
56 match pat.node {
57 PatIdent(..) => {
58 !pat_is_variant_or_struct(dm, pat) &&
59 !pat_is_const(dm, pat)
60 }
61 _ => false
62 }
63 }
64
65 pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &Pat) -> bool {
66 match pat.node {
67 PatIdent(..) => pat_is_binding(dm, pat),
68 PatWild | PatWildMulti => true,
69 _ => false
70 }
71 }
72
73 /// Call `it` on every "binding" in a pattern, e.g., on `a` in
74 /// `match foo() { Some(a) => (), None => () }`
75 pub fn pat_bindings(dm: &resolve::DefMap,
76 pat: &Pat,
77 it: |BindingMode, NodeId, Span, &Path|) {
78 walk_pat(pat, |p| {
79 match p.node {
80 PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
81 it(binding_mode, p.id, p.span, pth);
82 }
83 _ => {}
84 }
85 true
86 });
87 }
88
89 /// Checks if the pattern contains any patterns that bind something to
90 /// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
91 pub fn pat_contains_bindings(dm: &resolve::DefMap, pat: &Pat) -> bool {
92 let mut contains_bindings = false;
93 walk_pat(pat, |p| {
94 if pat_is_binding(dm, p) {
95 contains_bindings = true;
96 false // there's at least one binding, can short circuit now.
97 } else {
98 true
99 }
100 });
101 contains_bindings
102 }
103
104 pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> {
105 match pat.node {
106 PatIdent(BindByValue(_), ref path, None) => {
107 Some(path)
108 }
109 _ => {
110 None
111 }
112 }
113 }
librustc/middle/pat_util.rs:103:1-103:1 -fn- definition:
pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> {
match pat.node {
PatIdent(BindByValue(_), ref path, None) => {
references:- 2librustc/middle/trans/_match.rs:
1995: // it assumes it is matching against a valid value.
1996: match simple_identifier(pat) {
1997: Some(path) => {
--
2062: match simple_identifier(pat) {
2063: Some(path) => {
librustc/middle/pat_util.rs:18:1-18:1 -NK_AS_STR_TODO- definition:
pub type PatIdMap = HashMap<Ident, NodeId>;
// This is used because same-named variables in alternative patterns need to
// use the NodeId of their namesake in the first pattern.
references:- 222: // use the NodeId of their namesake in the first pattern.
23: pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap {
24: let mut map = HashMap::new();
librustc/middle/typeck/check/_match.rs:
106: pub fcx: &'a FnCtxt<'a>,
107: pub map: PatIdMap,
108: }
librustc/middle/pat_util.rs:42:1-42:1 -fn- definition:
pub fn pat_is_const(dm: &resolve::DefMap, pat: &Pat) -> bool {
match pat.node {
PatIdent(_, _, None) | PatEnum(..) => {
references:- 358: !pat_is_variant_or_struct(dm, pat) &&
59: !pat_is_const(dm, pat)
60: }
librustc/middle/typeck/check/_match.rs:
469: ast::PatEnum(..) |
470: ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
471: let const_did = ast_util::def_id_of_def(tcx.def_map.borrow()
librustc/middle/trans/_match.rs:
603: ast::PatEnum(..) |
604: ast::PatIdent(_, _, None) if pat_is_const(&tcx.def_map, p) => {
605: let const_def = tcx.def_map.borrow().get_copy(&p.id);
librustc/middle/pat_util.rs:22:58-22:58 -fn- definition:
// use the NodeId of their namesake in the first pattern.
pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap {
let mut map = HashMap::new();
references:- 3librustc/middle/typeck/check/mod.rs:
3344: fcx: fcx,
3345: map: pat_id_map(&tcx.def_map, local.pat),
3346: };
librustc/middle/typeck/check/_match.rs:
42: fcx: fcx,
43: map: pat_id_map(&tcx.def_map, *arm.pats.get(0)),
44: };
librustc/middle/typeck/check/mod.rs:
501: fcx: &fcx,
502: map: pat_id_map(&tcx.def_map, input.pat),
503: };
librustc/middle/pat_util.rs:30:1-30:1 -fn- definition:
pub fn pat_is_variant_or_struct(dm: &resolve::DefMap, pat: &Pat) -> bool {
match pat.node {
PatEnum(_, _) | PatIdent(_, _, None) | PatStruct(..) => {
references:- 257: PatIdent(..) => {
58: !pat_is_variant_or_struct(dm, pat) &&
59: !pat_is_const(dm, pat)
librustc/middle/trans/_match.rs:
626: ast::PatIdent(_, _, None)
627: if pat_is_variant_or_struct(&tcx.def_map, p) => {
628: if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
librustc/middle/pat_util.rs:54:1-54:1 -fn- definition:
pub fn pat_is_binding(dm: &resolve::DefMap, pat: &Pat) -> bool {
match pat.node {
PatIdent(..) => {
references:- 1366: match pat.node {
67: PatIdent(..) => pat_is_binding(dm, pat),
68: PatWild | PatWildMulti => true,
--
79: match p.node {
80: PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
81: it(binding_mode, p.id, p.span, pth);
--
93: walk_pat(pat, |p| {
94: if pat_is_binding(dm, p) {
95: contains_bindings = true;
librustc/middle/expr_use_visitor.rs:
701: return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
702: if pat_util::pat_is_binding(def_map, pat) {
703: let tcx = typer.tcx();
librustc/middle/trans/_match.rs:
2164: ast::PatIdent(pat_binding_mode, ref path, inner) => {
2165: if pat_is_binding(&tcx.def_map, pat) {
2166: // Allocate the stack slot where the value of this
librustc/middle/trans/debuginfo.rs:
2508: // introduce an artificial scope
2509: if pat_util::pat_is_binding(def_map, pat) {
librustc/middle/typeck/check/mod.rs:
409: ast::PatIdent(_, ref path, _)
410: if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
411: self.assign(p.id, None);
librustc/middle/typeck/check/writeback.rs:
55: // Privacy needs the type for the whole pattern, not just each binding
56: if !pat_util::pat_is_binding(&fcx.tcx().def_map, arg.pat) {
57: wbcx.visit_node_id(ResolvingPattern(arg.pat.span),
librustc/middle/check_match.rs:
972: walk_pat(*pat, |p| {
973: if pat_is_binding(def_map, p) {
974: match p.node {
librustc/middle/lint.rs:
1372: ast::PatIdent(ast::BindByValue(ast::MutMutable),
1373: ref path, _) if pat_util::pat_is_binding(&cx.tcx.def_map, p) => {
1374: // `let mut _a = 1;` doesn't need a warning.
librustc/middle/typeck/check/_match.rs:
476: }
477: ast::PatIdent(bm, ref name, sub) if pat_is_binding(&tcx.def_map, pat) => {
478: let typ = fcx.local_ty(pat.span, pat.id);
librustc/middle/pat_util.rs:74:48-74:48 -fn- definition:
/// `match foo() { Some(a) => (), None => () }`
pub fn pat_bindings(dm: &resolve::DefMap,
pat: &Pat,
references:- 1624: let mut map = HashMap::new();
25: pat_bindings(dm, pat, |_bm, p_id, _s, n| {
26: map.insert(path_to_ident(n), p_id);
librustc/middle/expr_use_visitor.rs:
461: let delegate = &mut self.delegate;
462: pat_util::pat_bindings(&self.typer.tcx().def_map, local.pat, |_, id, span, _| {
463: delegate.decl_without_init(id, span);
librustc/middle/trans/_match.rs:
1840: let mut bindings_map = HashMap::new();
1841: pat_bindings(&tcx.def_map, pat, |bm, p_id, span, path| {
1842: let ident = path_to_ident(path);
--
2031: let tcx = bcx.tcx();
2032: pat_bindings(&tcx.def_map, pat, |_, p_id, _, path| {
2033: let scope = cleanup::var_scope(tcx, p_id);
librustc/middle/trans/debuginfo.rs:
2397: for &arg_pat in arg_pats.iter() {
2398: pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2399: let ident = ast_util::path_to_ident(path_ref);
librustc/middle/resolve.rs:
4029: let mut result = HashMap::new();
4030: pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path| {
4031: let name = mtwt::resolve(path_to_ident(path));
librustc/middle/typeck/check/mod.rs:
492: // Create type variables for each argument.
493: pat_util::pat_bindings(&tcx.def_map,
494: input.pat,
librustc/middle/typeck/check/regionck.rs:
363: debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
364: pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
365: // If we have a variable that contains region'd data, that
librustc/middle/check_match.rs:
936: for pat in pats.iter() {
937: pat_bindings(def_map, *pat, |bm, _, span, _path| {
938: match bm {
librustc/middle/liveness.rs:
400: fn visit_local(ir: &mut IrMaps, local: &Local) {
401: pat_util::pat_bindings(&ir.tcx.def_map, local.pat, |bm, p_id, sp, path| {
402: debug!("adding local variable {}", p_id);
--
1541: for arg in decl.inputs.iter() {
1542: pat_util::pat_bindings(&self.ir.tcx.def_map,
1543: arg.pat,
librustc/middle/trans/debuginfo.rs:
516: pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
517: let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {