1 // Copyright 2015 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.
12 * This module contains the code to convert from the wacky tcx data
13 * structures into the hair. The `builder` is generally ignorant of
14 * the tcx etc, and instead goes through the `Cx` for most of its
20 use rustc
::mir
::transform
::MirSource
;
22 use rustc
::middle
::const_val
::ConstVal
;
23 use rustc_const_eval
as const_eval
;
24 use rustc_data_structures
::indexed_vec
::Idx
;
25 use rustc
::dep_graph
::DepNode
;
26 use rustc
::hir
::def_id
::DefId
;
27 use rustc
::hir
::intravisit
::FnKind
;
28 use rustc
::hir
::map
::blocks
::FnLikeNode
;
29 use rustc
::infer
::InferCtxt
;
30 use rustc
::ty
::subst
::Subst
;
31 use rustc
::ty
::{self, Ty, TyCtxt}
;
32 use syntax
::parse
::token
;
34 use rustc_const_math
::{ConstInt, ConstUsize}
;
36 #[derive(Copy, Clone)]
37 pub struct Cx
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
38 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
39 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
40 constness
: hir
::Constness
,
42 /// True if this constant/function needs overflow checks.
46 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
47 pub fn new(infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
49 -> Cx
<'a
, 'gcx
, 'tcx
> {
50 let constness
= match src
{
52 MirSource
::Static(..) => hir
::Constness
::Const
,
53 MirSource
::Fn(id
) => {
54 let fn_like
= FnLikeNode
::from_node(infcx
.tcx
.map
.get(id
));
55 match fn_like
.map(|f
| f
.kind()) {
56 Some(FnKind
::ItemFn(_
, _
, _
, c
, ..)) => c
,
57 Some(FnKind
::Method(_
, m
, ..)) => m
.constness
,
58 _
=> hir
::Constness
::NotConst
61 MirSource
::Promoted(..) => bug
!()
64 let src_node_id
= src
.item_id();
66 // We are going to be accessing various tables
67 // generated by TypeckItemBody; we also assume
68 // that the body passes type check. These tables
69 // are not individually tracked, so just register
71 let src_def_id
= infcx
.tcx
.map
.local_def_id(src_node_id
);
72 infcx
.tcx
.dep_graph
.read(DepNode
::TypeckItemBody(src_def_id
));
74 let attrs
= infcx
.tcx
.map
.attrs(src_node_id
);
76 // Some functions always have overflow checks enabled,
77 // however, they may not get codegen'd, depending on
78 // the settings for the crate they are translated in.
79 let mut check_overflow
= attrs
.iter().any(|item
| {
80 item
.check_name("rustc_inherit_overflow_checks")
83 // Respect -Z force-overflow-checks=on and -C debug-assertions.
84 check_overflow
|= infcx
.tcx
.sess
.opts
.debugging_opts
.force_overflow_checks
85 .unwrap_or(infcx
.tcx
.sess
.opts
.debug_assertions
);
87 // Constants and const fn's always need overflow checks.
88 check_overflow
|= constness
== hir
::Constness
::Const
;
94 check_overflow
: check_overflow
99 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
100 /// Normalizes `ast` into the appropriate `mirror` type.
101 pub fn mirror
<M
: Mirror
<'tcx
>>(&mut self, ast
: M
) -> M
::Output
{
102 ast
.make_mirror(self)
105 pub fn usize_ty(&mut self) -> Ty
<'tcx
> {
109 pub fn usize_literal(&mut self, value
: u64) -> Literal
<'tcx
> {
110 match ConstUsize
::new(value
, self.tcx
.sess
.target
.uint_type
) {
111 Ok(val
) => Literal
::Value { value: ConstVal::Integral(ConstInt::Usize(val))}
,
112 Err(_
) => bug
!("usize literal out of range for target"),
116 pub fn bool_ty(&mut self) -> Ty
<'tcx
> {
120 pub fn unit_ty(&mut self) -> Ty
<'tcx
> {
124 pub fn str_literal(&mut self, value
: token
::InternedString
) -> Literal
<'tcx
> {
125 Literal
::Value { value: ConstVal::Str(value) }
128 pub fn true_literal(&mut self) -> Literal
<'tcx
> {
129 Literal
::Value { value: ConstVal::Bool(true) }
132 pub fn false_literal(&mut self) -> Literal
<'tcx
> {
133 Literal
::Value { value: ConstVal::Bool(false) }
136 pub fn const_eval_literal(&mut self, e
: &hir
::Expr
) -> Literal
<'tcx
> {
138 value
: const_eval
::eval_const_expr(self.tcx
.global_tcx(), e
)
142 pub fn trait_method(&mut self,
147 -> (Ty
<'tcx
>, Literal
<'tcx
>) {
148 let method_name
= token
::intern(method_name
);
149 let substs
= self.tcx
.mk_substs_trait(self_ty
, params
);
150 for trait_item
in self.tcx
.trait_items(trait_def_id
).iter() {
152 ty
::ImplOrTraitItem
::MethodTraitItem(ref method
) => {
153 if method
.name
== method_name
{
154 let method_ty
= self.tcx
.lookup_item_type(method
.def_id
);
155 let method_ty
= method_ty
.ty
.subst(self.tcx
, substs
);
156 return (method_ty
, Literal
::Item
{
157 def_id
: method
.def_id
,
162 ty
::ImplOrTraitItem
::ConstTraitItem(..) |
163 ty
::ImplOrTraitItem
::TypeTraitItem(..) => {}
167 bug
!("found no method `{}` in `{:?}`", method_name
, trait_def_id
);
170 pub fn num_variants(&mut self, adt_def
: ty
::AdtDef
) -> usize {
171 adt_def
.variants
.len()
174 pub fn all_fields(&mut self, adt_def
: ty
::AdtDef
, variant_index
: usize) -> Vec
<Field
> {
175 (0..adt_def
.variants
[variant_index
].fields
.len())
180 pub fn needs_drop(&mut self, ty
: Ty
<'tcx
>) -> bool
{
181 let ty
= self.tcx
.lift_to_global(&ty
).unwrap_or_else(|| {
182 bug
!("MIR: Cx::needs_drop({}) got \
183 type with inference types/regions", ty
);
185 self.tcx
.type_needs_drop_given_env(ty
, &self.infcx
.parameter_environment
)
188 pub fn tcx(&self) -> TyCtxt
<'a
, 'gcx
, 'tcx
> {
192 pub fn check_overflow(&self) -> bool
{