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.
11 //! This module contains the code to convert from the wacky tcx data
12 //! structures into the hair. The `builder` is generally ignorant of
13 //! the tcx etc, and instead goes through the `Cx` for most of its
18 use rustc
::mir
::transform
::MirSource
;
20 use rustc
::middle
::const_val
::ConstVal
;
21 use rustc_const_eval
::{ConstContext, fatal_const_eval_err}
;
22 use rustc_data_structures
::indexed_vec
::Idx
;
23 use rustc
::hir
::def_id
::DefId
;
24 use rustc
::hir
::map
::blocks
::FnLikeNode
;
25 use rustc
::infer
::InferCtxt
;
26 use rustc
::ty
::subst
::Subst
;
27 use rustc
::ty
::{self, Ty, TyCtxt}
;
28 use syntax
::symbol
::{Symbol, InternedString}
;
30 use rustc_const_math
::{ConstInt, ConstUsize}
;
32 #[derive(Copy, Clone)]
33 pub struct Cx
<'a
, 'gcx
: 'a
+ 'tcx
, 'tcx
: 'a
> {
34 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
35 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
36 constness
: hir
::Constness
,
38 /// True if this constant/function needs overflow checks.
42 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
43 pub fn new(infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>, src
: MirSource
) -> Cx
<'a
, 'gcx
, 'tcx
> {
44 let constness
= match src
{
46 MirSource
::Static(..) => hir
::Constness
::Const
,
47 MirSource
::Fn(id
) => {
48 let fn_like
= FnLikeNode
::from_node(infcx
.tcx
.hir
.get(id
));
49 fn_like
.map_or(hir
::Constness
::NotConst
, |f
| f
.constness())
51 MirSource
::Promoted(..) => bug
!(),
54 let attrs
= infcx
.tcx
.hir
.attrs(src
.item_id());
56 // Some functions always have overflow checks enabled,
57 // however, they may not get codegen'd, depending on
58 // the settings for the crate they are translated in.
59 let mut check_overflow
= attrs
.iter()
60 .any(|item
| item
.check_name("rustc_inherit_overflow_checks"));
62 // Respect -C overflow-checks.
63 check_overflow
|= infcx
.tcx
.sess
.overflow_checks();
65 // Constants and const fn's always need overflow checks.
66 check_overflow
|= constness
== hir
::Constness
::Const
;
72 check_overflow
: check_overflow
,
77 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
78 /// Normalizes `ast` into the appropriate `mirror` type.
79 pub fn mirror
<M
: Mirror
<'tcx
>>(&mut self, ast
: M
) -> M
::Output
{
83 pub fn usize_ty(&mut self) -> Ty
<'tcx
> {
87 pub fn usize_literal(&mut self, value
: u64) -> Literal
<'tcx
> {
88 match ConstUsize
::new(value
, self.tcx
.sess
.target
.uint_type
) {
89 Ok(val
) => Literal
::Value { value: ConstVal::Integral(ConstInt::Usize(val)) }
,
90 Err(_
) => bug
!("usize literal out of range for target"),
94 pub fn bool_ty(&mut self) -> Ty
<'tcx
> {
98 pub fn unit_ty(&mut self) -> Ty
<'tcx
> {
102 pub fn str_literal(&mut self, value
: InternedString
) -> Literal
<'tcx
> {
103 Literal
::Value { value: ConstVal::Str(value) }
106 pub fn true_literal(&mut self) -> Literal
<'tcx
> {
107 Literal
::Value { value: ConstVal::Bool(true) }
110 pub fn false_literal(&mut self) -> Literal
<'tcx
> {
111 Literal
::Value { value: ConstVal::Bool(false) }
114 pub fn const_eval_literal(&mut self, e
: &hir
::Expr
) -> Literal
<'tcx
> {
115 let tcx
= self.tcx
.global_tcx();
116 match ConstContext
::with_tables(tcx
, self.tables()).eval(e
) {
117 Ok(value
) => Literal
::Value { value: value }
,
118 Err(s
) => fatal_const_eval_err(tcx
, &s
, e
.span
, "expression")
122 pub fn trait_method(&mut self,
127 -> (Ty
<'tcx
>, Literal
<'tcx
>) {
128 let method_name
= Symbol
::intern(method_name
);
129 let substs
= self.tcx
.mk_substs_trait(self_ty
, params
);
130 for item
in self.tcx
.associated_items(trait_def_id
) {
131 if item
.kind
== ty
::AssociatedKind
::Method
&& item
.name
== method_name
{
132 let method_ty
= self.tcx
.item_type(item
.def_id
);
133 let method_ty
= method_ty
.subst(self.tcx
, substs
);
142 bug
!("found no method `{}` in `{:?}`", method_name
, trait_def_id
);
145 pub fn num_variants(&mut self, adt_def
: &ty
::AdtDef
) -> usize {
146 adt_def
.variants
.len()
149 pub fn all_fields(&mut self, adt_def
: &ty
::AdtDef
, variant_index
: usize) -> Vec
<Field
> {
150 (0..adt_def
.variants
[variant_index
].fields
.len())
155 pub fn needs_drop(&mut self, ty
: Ty
<'tcx
>) -> bool
{
156 let ty
= self.tcx
.lift_to_global(&ty
).unwrap_or_else(|| {
157 bug
!("MIR: Cx::needs_drop({}) got \
158 type with inference types/regions",
161 self.tcx
.type_needs_drop_given_env(ty
, &self.infcx
.parameter_environment
)
164 pub fn tcx(&self) -> TyCtxt
<'a
, 'gcx
, 'tcx
> {
168 pub fn tables(&self) -> &'a ty
::TypeckTables
<'gcx
> {
169 self.infcx
.tables
.expect_interned()
172 pub fn check_overflow(&self) -> bool
{