1 // Copyright 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.
11 // Checks that all rvalues in a crate have statically known size. check_crate
12 // is the public starting point.
14 use rustc
::dep_graph
::DepNode
;
15 use rustc
::middle
::expr_use_visitor
as euv
;
17 use rustc
::middle
::mem_categorization
as mc
;
18 use rustc
::ty
::{self, TyCtxt, ParameterEnvironment}
;
19 use rustc
::traits
::ProjectionMode
;
22 use rustc
::hir
::intravisit
;
24 use syntax
::codemap
::Span
;
26 pub fn check_crate(tcx
: &TyCtxt
) {
27 let mut rvcx
= RvalueContext { tcx: tcx }
;
28 tcx
.visit_all_items_in_krate(DepNode
::RvalueCheck
, &mut rvcx
);
31 struct RvalueContext
<'a
, 'tcx
: 'a
> {
32 tcx
: &'a TyCtxt
<'tcx
>,
35 impl<'a
, 'tcx
, 'v
> intravisit
::Visitor
<'v
> for RvalueContext
<'a
, 'tcx
> {
36 fn visit_fn(&mut self,
37 fk
: intravisit
::FnKind
<'v
>,
43 // FIXME (@jroesch) change this to be an inference context
44 let param_env
= ParameterEnvironment
::for_item(self.tcx
, fn_id
);
45 let infcx
= infer
::new_infer_ctxt(self.tcx
,
47 Some(param_env
.clone()),
48 ProjectionMode
::AnyFinal
);
49 let mut delegate
= RvalueContextDelegate { tcx: self.tcx, param_env: ¶m_env }
;
50 let mut euv
= euv
::ExprUseVisitor
::new(&mut delegate
, &infcx
);
53 intravisit
::walk_fn(self, fk
, fd
, b
, s
)
57 struct RvalueContextDelegate
<'a
, 'tcx
: 'a
> {
58 tcx
: &'a TyCtxt
<'tcx
>,
59 param_env
: &'a ty
::ParameterEnvironment
<'a
,'tcx
>,
62 impl<'a
, 'tcx
> euv
::Delegate
<'tcx
> for RvalueContextDelegate
<'a
, 'tcx
> {
67 _
: euv
::ConsumeMode
) {
68 debug
!("consume; cmt: {:?}; type: {:?}", *cmt
, cmt
.ty
);
69 if !cmt
.ty
.is_sized(self.param_env
, span
) {
70 span_err
!(self.tcx
.sess
, span
, E0161
,
71 "cannot move a value of type {0}: the size of {0} cannot be statically determined",
76 fn matched_pat(&mut self,
77 _matched_pat
: &hir
::Pat
,
79 _mode
: euv
::MatchMode
) {}
81 fn consume_pat(&mut self,
82 _consume_pat
: &hir
::Pat
,
84 _mode
: euv
::ConsumeMode
) {
88 _borrow_id
: ast
::NodeId
,
91 _loan_region
: ty
::Region
,
93 _loan_cause
: euv
::LoanCause
) {
96 fn decl_without_init(&mut self,
102 _assignment_id
: ast
::NodeId
,
103 _assignment_span
: Span
,
104 _assignee_cmt
: mc
::cmt
,
105 _mode
: euv
::MutateMode
) {