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
;
16 use rustc
::middle
::mem_categorization
as mc
;
17 use rustc
::ty
::{self, TyCtxt, ParameterEnvironment}
;
18 use rustc
::traits
::Reveal
;
21 use rustc
::hir
::intravisit
;
25 pub fn check_crate
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) {
26 let mut rvcx
= RvalueContext { tcx: tcx }
;
27 tcx
.visit_all_items_in_krate(DepNode
::RvalueCheck
, &mut rvcx
);
30 struct RvalueContext
<'a
, 'tcx
: 'a
> {
31 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
34 impl<'a
, 'tcx
, 'v
> intravisit
::Visitor
<'v
> for RvalueContext
<'a
, 'tcx
> {
35 fn visit_fn(&mut self,
36 fk
: intravisit
::FnKind
<'v
>,
41 // FIXME (@jroesch) change this to be an inference context
42 let param_env
= ParameterEnvironment
::for_item(self.tcx
, fn_id
);
43 self.tcx
.infer_ctxt(None
, Some(param_env
.clone()),
44 Reveal
::NotSpecializable
).enter(|infcx
| {
45 let mut delegate
= RvalueContextDelegate
{
49 let mut euv
= euv
::ExprUseVisitor
::new(&mut delegate
, &infcx
);
52 intravisit
::walk_fn(self, fk
, fd
, b
, s
, fn_id
)
56 struct RvalueContextDelegate
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
57 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
58 param_env
: &'a ty
::ParameterEnvironment
<'gcx
>,
61 impl<'a
, 'gcx
, 'tcx
> euv
::Delegate
<'tcx
> for RvalueContextDelegate
<'a
, 'gcx
, 'tcx
> {
66 _
: euv
::ConsumeMode
) {
67 debug
!("consume; cmt: {:?}; type: {:?}", *cmt
, cmt
.ty
);
68 let ty
= self.tcx
.lift_to_global(&cmt
.ty
).unwrap();
69 if !ty
.is_sized(self.tcx
.global_tcx(), 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
: &'tcx 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
) {