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
::{ConstEvalErr, ConstVal}
;
21 use rustc_const_eval
::ConstContext
;
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
::middle
::region
::RegionMaps
;
26 use rustc
::infer
::InferCtxt
;
27 use rustc
::ty
::subst
::Subst
;
28 use rustc
::ty
::{self, Ty, TyCtxt}
;
29 use syntax
::symbol
::Symbol
;
31 use rustc_const_math
::{ConstInt, ConstUsize}
;
35 pub struct Cx
<'a
, 'gcx
: 'a
+ 'tcx
, 'tcx
: 'a
> {
36 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
37 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
38 pub param_env
: ty
::ParamEnv
<'tcx
>,
39 pub region_maps
: Rc
<RegionMaps
>,
41 /// This is `Constness::Const` if we are compiling a `static`,
42 /// `const`, or the body of a `const fn`.
43 constness
: hir
::Constness
,
45 /// What are we compiling?
48 /// True if this constant/function needs overflow checks.
52 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
53 pub fn new(infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>, src
: MirSource
) -> Cx
<'a
, 'gcx
, 'tcx
> {
54 let constness
= match src
{
56 MirSource
::Static(..) => hir
::Constness
::Const
,
57 MirSource
::Fn(id
) => {
58 let fn_like
= FnLikeNode
::from_node(infcx
.tcx
.hir
.get(id
));
59 fn_like
.map_or(hir
::Constness
::NotConst
, |f
| f
.constness())
61 MirSource
::Promoted(..) => bug
!(),
65 let src_id
= src
.item_id();
66 let src_def_id
= tcx
.hir
.local_def_id(src_id
);
68 let param_env
= tcx
.param_env(src_def_id
);
69 let region_maps
= tcx
.region_maps(src_def_id
);
71 let attrs
= tcx
.hir
.attrs(src_id
);
73 // Some functions always have overflow checks enabled,
74 // however, they may not get codegen'd, depending on
75 // the settings for the crate they are translated in.
76 let mut check_overflow
= attrs
.iter()
77 .any(|item
| item
.check_name("rustc_inherit_overflow_checks"));
79 // Respect -C overflow-checks.
80 check_overflow
|= tcx
.sess
.overflow_checks();
82 // Constants and const fn's always need overflow checks.
83 check_overflow
|= constness
== hir
::Constness
::Const
;
85 Cx { tcx, infcx, param_env, region_maps, constness, src, check_overflow }
89 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
90 /// Normalizes `ast` into the appropriate `mirror` type.
91 pub fn mirror
<M
: Mirror
<'tcx
>>(&mut self, ast
: M
) -> M
::Output
{
95 pub fn usize_ty(&mut self) -> Ty
<'tcx
> {
99 pub fn usize_literal(&mut self, value
: u64) -> Literal
<'tcx
> {
100 match ConstUsize
::new(value
, self.tcx
.sess
.target
.uint_type
) {
101 Ok(val
) => Literal
::Value { value: ConstVal::Integral(ConstInt::Usize(val)) }
,
102 Err(_
) => bug
!("usize literal out of range for target"),
106 pub fn bool_ty(&mut self) -> Ty
<'tcx
> {
110 pub fn unit_ty(&mut self) -> Ty
<'tcx
> {
114 pub fn true_literal(&mut self) -> Literal
<'tcx
> {
115 Literal
::Value { value: ConstVal::Bool(true) }
118 pub fn false_literal(&mut self) -> Literal
<'tcx
> {
119 Literal
::Value { value: ConstVal::Bool(false) }
122 pub fn const_eval_literal(&mut self, e
: &hir
::Expr
) -> Literal
<'tcx
> {
123 let tcx
= self.tcx
.global_tcx();
124 match ConstContext
::with_tables(tcx
, self.tables()).eval(e
) {
125 Ok(value
) => Literal
::Value { value: value }
,
126 Err(s
) => self.fatal_const_eval_err(&s
, e
.span
, "expression")
130 pub fn fatal_const_eval_err(&self,
131 err
: &ConstEvalErr
<'tcx
>,
136 err
.report(self.tcx
, primary_span
, primary_kind
);
137 self.tcx
.sess
.abort_if_errors();
141 pub fn trait_method(&mut self,
146 -> (Ty
<'tcx
>, Literal
<'tcx
>) {
147 let method_name
= Symbol
::intern(method_name
);
148 let substs
= self.tcx
.mk_substs_trait(self_ty
, params
);
149 for item
in self.tcx
.associated_items(trait_def_id
) {
150 if item
.kind
== ty
::AssociatedKind
::Method
&& item
.name
== method_name
{
151 let method_ty
= self.tcx
.type_of(item
.def_id
);
152 let method_ty
= method_ty
.subst(self.tcx
, substs
);
155 value
: ConstVal
::Function(item
.def_id
, substs
),
160 bug
!("found no method `{}` in `{:?}`", method_name
, trait_def_id
);
163 pub fn num_variants(&mut self, adt_def
: &ty
::AdtDef
) -> usize {
164 adt_def
.variants
.len()
167 pub fn all_fields(&mut self, adt_def
: &ty
::AdtDef
, variant_index
: usize) -> Vec
<Field
> {
168 (0..adt_def
.variants
[variant_index
].fields
.len())
173 pub fn needs_drop(&mut self, ty
: Ty
<'tcx
>) -> bool
{
174 let (ty
, param_env
) = self.tcx
.lift_to_global(&(ty
, self.param_env
)).unwrap_or_else(|| {
175 bug
!("MIR: Cx::needs_drop({:?}, {:?}) got \
176 type with inference types/regions",
179 ty
.needs_drop(self.tcx
.global_tcx(), param_env
)
182 pub fn tcx(&self) -> TyCtxt
<'a
, 'gcx
, 'tcx
> {
186 pub fn tables(&self) -> &'a ty
::TypeckTables
<'gcx
> {
187 self.infcx
.tables
.expect_interned()
190 pub fn check_overflow(&self) -> bool
{