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.
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.
14 use borrowck
::gather_loans
::move_error
::MoveSpanAndPath
;
15 use borrowck
::gather_loans
::move_error
::{MoveError, MoveErrorCollector}
;
16 use borrowck
::move_data
::*;
17 use rustc
::middle
::expr_use_visitor
as euv
;
18 use rustc
::middle
::mem_categorization
as mc
;
19 use rustc
::middle
::mem_categorization
::Categorization
;
20 use rustc
::middle
::mem_categorization
::InteriorOffsetKind
as Kind
;
25 use syntax
::codemap
::Span
;
26 use rustc
::hir
::{self, PatKind}
;
28 struct GatherMoveInfo
<'tcx
> {
32 span_path_opt
: Option
<MoveSpanAndPath
>
35 pub fn gather_decl
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
36 move_data
: &MoveData
<'tcx
>,
39 var_id
: ast
::NodeId
) {
40 let ty
= bccx
.tcx
.node_id_to_type(var_id
);
41 let loan_path
= Rc
::new(LoanPath
::new(LpVar(var_id
), ty
));
42 move_data
.add_move(bccx
.tcx
, loan_path
, decl_id
, Declared
);
45 pub fn gather_move_from_expr
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
46 move_data
: &MoveData
<'tcx
>,
47 move_error_collector
: &mut MoveErrorCollector
<'tcx
>,
48 move_expr_id
: ast
::NodeId
,
50 move_reason
: euv
::MoveReason
) {
51 let kind
= match move_reason
{
52 euv
::DirectRefMove
| euv
::PatBindingMove
=> MoveExpr
,
53 euv
::CaptureMove
=> Captured
55 let move_info
= GatherMoveInfo
{
61 gather_move(bccx
, move_data
, move_error_collector
, move_info
);
64 pub fn gather_match_variant
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
65 move_data
: &MoveData
<'tcx
>,
66 _move_error_collector
: &mut MoveErrorCollector
<'tcx
>,
69 mode
: euv
::MatchMode
) {
71 debug
!("gather_match_variant(move_pat={}, cmt={:?}, mode={:?})",
72 move_pat
.id
, cmt
, mode
);
74 let opt_lp
= opt_loan_path(&cmt
);
78 LpDowncast(ref base_lp
, _
) =>
79 move_data
.add_variant_match(
80 tcx
, lp
.clone(), move_pat
.id
, base_lp
.clone(), mode
),
81 _
=> bug
!("should only call gather_match_variant \
82 for cat_downcast cmt"),
86 // We get None when input to match is non-path (e.g.
87 // temporary result like a function call). Since no
88 // loan-path is being matched, no need to record a
95 pub fn gather_move_from_pat
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
96 move_data
: &MoveData
<'tcx
>,
97 move_error_collector
: &mut MoveErrorCollector
<'tcx
>,
100 let pat_span_path_opt
= match move_pat
.node
{
101 PatKind
::Ident(_
, ref path1
, _
) => {
102 Some(MoveSpanAndPath
{span
: move_pat
.span
,
103 name
: path1
.node
.name
})
107 let move_info
= GatherMoveInfo
{
111 span_path_opt
: pat_span_path_opt
,
113 gather_move(bccx
, move_data
, move_error_collector
, move_info
);
116 fn gather_move
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
117 move_data
: &MoveData
<'tcx
>,
118 move_error_collector
: &mut MoveErrorCollector
<'tcx
>,
119 move_info
: GatherMoveInfo
<'tcx
>) {
120 debug
!("gather_move(move_id={}, cmt={:?})",
121 move_info
.id
, move_info
.cmt
);
123 let potentially_illegal_move
=
124 check_and_get_illegal_move_origin(bccx
, &move_info
.cmt
);
125 match potentially_illegal_move
{
126 Some(illegal_move_origin
) => {
127 debug
!("illegal_move_origin={:?}", illegal_move_origin
);
128 let error
= MoveError
::with_move_info(illegal_move_origin
,
129 move_info
.span_path_opt
);
130 move_error_collector
.add_error(error
);
136 match opt_loan_path(&move_info
.cmt
) {
138 move_data
.add_move(bccx
.tcx
, loan_path
,
139 move_info
.id
, move_info
.kind
);
142 // move from rvalue or raw pointer, hence ok
147 pub fn gather_assignment
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
148 move_data
: &MoveData
<'tcx
>,
149 assignment_id
: ast
::NodeId
,
150 assignment_span
: Span
,
151 assignee_loan_path
: Rc
<LoanPath
<'tcx
>>,
152 assignee_id
: ast
::NodeId
,
153 mode
: euv
::MutateMode
) {
154 move_data
.add_assignment(bccx
.tcx
,
162 // (keep in sync with move_error::report_cannot_move_out_of )
163 fn check_and_get_illegal_move_origin
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
165 -> Option
<mc
::cmt
<'tcx
>> {
167 Categorization
::Deref(_
, _
, mc
::BorrowedPtr(..)) |
168 Categorization
::Deref(_
, _
, mc
::Implicit(..)) |
169 Categorization
::Deref(_
, _
, mc
::UnsafePtr(..)) |
170 Categorization
::StaticItem
=> {
174 Categorization
::Rvalue(..) |
175 Categorization
::Local(..) |
176 Categorization
::Upvar(..) => {
180 Categorization
::Downcast(ref b
, _
) |
181 Categorization
::Interior(ref b
, mc
::InteriorField(_
)) |
182 Categorization
::Interior(ref b
, mc
::InteriorElement(Kind
::Pattern
, _
)) => {
184 ty
::TyStruct(def
, _
) | ty
::TyEnum(def
, _
) => {
188 check_and_get_illegal_move_origin(bccx
, b
)
192 check_and_get_illegal_move_origin(bccx
, b
)
197 Categorization
::Interior(_
, mc
::InteriorElement(Kind
::Index
, _
)) => {
198 // Forbid move of arr[i] for arr: [T; 3]; see RFC 533.
202 Categorization
::Deref(ref b
, _
, mc
::Unique
) => {
203 check_and_get_illegal_move_origin(bccx
, b
)