1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use rustc::dep_graph::DepNode;
use rustc::middle::expr_use_visitor as euv;
use rustc::middle::mem_categorization as mc;
use rustc::ty::{self, TyCtxt};
use rustc::traits::Reveal;
use rustc::hir;
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
use syntax::ast;
use syntax_pos::Span;
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let mut rvcx = RvalueContext { tcx: tcx };
tcx.visit_all_item_likes_in_krate(DepNode::RvalueCheck, &mut rvcx.as_deep_visitor());
}
struct RvalueContext<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
let body = self.tcx.hir.body(body_id);
self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
let mut delegate = RvalueContextDelegate {
tcx: infcx.tcx,
param_env: &infcx.parameter_environment
};
euv::ExprUseVisitor::new(&mut delegate, &infcx).consume_body(body);
});
self.visit_body(body);
}
}
struct RvalueContextDelegate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
param_env: &'a ty::ParameterEnvironment<'gcx>,
}
impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'gcx, 'tcx> {
fn consume(&mut self,
_: ast::NodeId,
span: Span,
cmt: mc::cmt<'tcx>,
_: euv::ConsumeMode) {
debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty);
let ty = self.tcx.lift_to_global(&cmt.ty).unwrap();
if !ty.is_sized(self.tcx.global_tcx(), self.param_env, span) {
span_err!(self.tcx.sess, span, E0161,
"cannot move a value of type {0}: the size of {0} cannot be statically determined",
ty);
}
}
fn matched_pat(&mut self,
_matched_pat: &hir::Pat,
_cmt: mc::cmt,
_mode: euv::MatchMode) {}
fn consume_pat(&mut self,
_consume_pat: &hir::Pat,
_cmt: mc::cmt,
_mode: euv::ConsumeMode) {
}
fn borrow(&mut self,
_borrow_id: ast::NodeId,
_borrow_span: Span,
_cmt: mc::cmt,
_loan_region: &'tcx ty::Region,
_bk: ty::BorrowKind,
_loan_cause: euv::LoanCause) {
}
fn decl_without_init(&mut self,
_id: ast::NodeId,
_span: Span) {
}
fn mutate(&mut self,
_assignment_id: ast::NodeId,
_assignment_span: Span,
_assignee_cmt: mc::cmt,
_mode: euv::MutateMode) {
}
}