]> git.proxmox.com Git - rustc.git/blame - src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
Merge tag 'upstream/1.5.0+dfsg1'
[rustc.git] / src / librustc_borrowck / borrowck / gather_loans / gather_moves.rs
CommitLineData
1a4d82fc
JJ
1// Copyright 2012-2013 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//! Computes moves.
12
13use borrowck::*;
14use borrowck::gather_loans::move_error::MoveSpanAndPath;
15use borrowck::gather_loans::move_error::{MoveError, MoveErrorCollector};
16use borrowck::move_data::*;
17use rustc::middle::expr_use_visitor as euv;
18use rustc::middle::mem_categorization as mc;
85aaf69f 19use rustc::middle::mem_categorization::InteriorOffsetKind as Kind;
1a4d82fc 20use rustc::middle::ty;
62682a34 21
1a4d82fc
JJ
22use std::rc::Rc;
23use syntax::ast;
24use syntax::codemap::Span;
e9174d1e 25use rustc_front::hir;
1a4d82fc
JJ
26
27struct GatherMoveInfo<'tcx> {
28 id: ast::NodeId,
29 kind: MoveKind,
30 cmt: mc::cmt<'tcx>,
31 span_path_opt: Option<MoveSpanAndPath>
32}
33
34pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
35 move_data: &MoveData<'tcx>,
36 decl_id: ast::NodeId,
37 _decl_span: Span,
38 var_id: ast::NodeId) {
c1a9b12d 39 let ty = bccx.tcx.node_id_to_type(var_id);
1a4d82fc
JJ
40 let loan_path = Rc::new(LoanPath::new(LpVar(var_id), ty));
41 move_data.add_move(bccx.tcx, loan_path, decl_id, Declared);
42}
43
44pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
45 move_data: &MoveData<'tcx>,
46 move_error_collector: &MoveErrorCollector<'tcx>,
47 move_expr_id: ast::NodeId,
48 cmt: mc::cmt<'tcx>,
49 move_reason: euv::MoveReason) {
50 let kind = match move_reason {
51 euv::DirectRefMove | euv::PatBindingMove => MoveExpr,
52 euv::CaptureMove => Captured
53 };
54 let move_info = GatherMoveInfo {
55 id: move_expr_id,
56 kind: kind,
57 cmt: cmt,
58 span_path_opt: None,
59 };
60 gather_move(bccx, move_data, move_error_collector, move_info);
61}
62
63pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
64 move_data: &MoveData<'tcx>,
65 _move_error_collector: &MoveErrorCollector<'tcx>,
e9174d1e 66 move_pat: &hir::Pat,
1a4d82fc
JJ
67 cmt: mc::cmt<'tcx>,
68 mode: euv::MatchMode) {
69 let tcx = bccx.tcx;
62682a34
SL
70 debug!("gather_match_variant(move_pat={}, cmt={:?}, mode={:?})",
71 move_pat.id, cmt, mode);
1a4d82fc
JJ
72
73 let opt_lp = opt_loan_path(&cmt);
74 match opt_lp {
75 Some(lp) => {
76 match lp.kind {
77 LpDowncast(ref base_lp, _) =>
78 move_data.add_variant_match(
79 tcx, lp.clone(), move_pat.id, base_lp.clone(), mode),
80 _ => panic!("should only call gather_match_variant \
81 for cat_downcast cmt"),
82 }
83 }
84 None => {
85 // We get None when input to match is non-path (e.g.
86 // temporary result like a function call). Since no
87 // loan-path is being matched, no need to record a
88 // downcast.
89 return;
90 }
91 }
92}
93
94pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
95 move_data: &MoveData<'tcx>,
96 move_error_collector: &MoveErrorCollector<'tcx>,
e9174d1e 97 move_pat: &hir::Pat,
1a4d82fc
JJ
98 cmt: mc::cmt<'tcx>) {
99 let pat_span_path_opt = match move_pat.node {
e9174d1e 100 hir::PatIdent(_, ref path1, _) => {
1a4d82fc 101 Some(MoveSpanAndPath{span: move_pat.span,
b039eaaf 102 name: path1.node.name})
1a4d82fc
JJ
103 },
104 _ => None,
105 };
106 let move_info = GatherMoveInfo {
107 id: move_pat.id,
108 kind: MovePat,
109 cmt: cmt,
110 span_path_opt: pat_span_path_opt,
111 };
112 gather_move(bccx, move_data, move_error_collector, move_info);
113}
114
115fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
116 move_data: &MoveData<'tcx>,
117 move_error_collector: &MoveErrorCollector<'tcx>,
118 move_info: GatherMoveInfo<'tcx>) {
62682a34
SL
119 debug!("gather_move(move_id={}, cmt={:?})",
120 move_info.id, move_info.cmt);
1a4d82fc
JJ
121
122 let potentially_illegal_move =
123 check_and_get_illegal_move_origin(bccx, &move_info.cmt);
124 match potentially_illegal_move {
125 Some(illegal_move_origin) => {
62682a34 126 debug!("illegal_move_origin={:?}", illegal_move_origin);
1a4d82fc
JJ
127 let error = MoveError::with_move_info(illegal_move_origin,
128 move_info.span_path_opt);
129 move_error_collector.add_error(error);
130 return
131 }
132 None => ()
133 }
134
135 match opt_loan_path(&move_info.cmt) {
136 Some(loan_path) => {
137 move_data.add_move(bccx.tcx, loan_path,
138 move_info.id, move_info.kind);
139 }
140 None => {
62682a34 141 // move from rvalue or raw pointer, hence ok
1a4d82fc
JJ
142 }
143 }
144}
145
146pub fn gather_assignment<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
147 move_data: &MoveData<'tcx>,
148 assignment_id: ast::NodeId,
149 assignment_span: Span,
150 assignee_loan_path: Rc<LoanPath<'tcx>>,
151 assignee_id: ast::NodeId,
152 mode: euv::MutateMode) {
153 move_data.add_assignment(bccx.tcx,
154 assignee_loan_path,
155 assignment_id,
156 assignment_span,
157 assignee_id,
158 mode);
159}
160
85aaf69f 161// (keep in sync with move_error::report_cannot_move_out_of )
1a4d82fc
JJ
162fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
163 cmt: &mc::cmt<'tcx>)
164 -> Option<mc::cmt<'tcx>> {
165 match cmt.cat {
166 mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
167 mc::cat_deref(_, _, mc::Implicit(..)) |
168 mc::cat_deref(_, _, mc::UnsafePtr(..)) |
169 mc::cat_static_item => {
170 Some(cmt.clone())
171 }
172
173 mc::cat_rvalue(..) |
174 mc::cat_local(..) |
175 mc::cat_upvar(..) => {
176 None
177 }
178
179 mc::cat_downcast(ref b, _) |
85aaf69f
SL
180 mc::cat_interior(ref b, mc::InteriorField(_)) |
181 mc::cat_interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => {
1a4d82fc 182 match b.ty.sty {
e9174d1e
SL
183 ty::TyStruct(def, _) | ty::TyEnum(def, _) => {
184 if def.has_dtor() {
1a4d82fc
JJ
185 Some(cmt.clone())
186 } else {
187 check_and_get_illegal_move_origin(bccx, b)
188 }
189 }
190 _ => {
191 check_and_get_illegal_move_origin(bccx, b)
192 }
193 }
194 }
195
85aaf69f
SL
196 mc::cat_interior(_, mc::InteriorElement(Kind::Index, _)) => {
197 // Forbid move of arr[i] for arr: [T; 3]; see RFC 533.
198 Some(cmt.clone())
199 }
200
1a4d82fc
JJ
201 mc::cat_deref(ref b, _, mc::Unique) => {
202 check_and_get_illegal_move_origin(bccx, b)
203 }
204 }
205}