]>
git.proxmox.com Git - rustc.git/blob - src/librustc_mir/hair/cx/mod.rs
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
19 use rustc_data_structures
::indexed_vec
::Idx
;
20 use rustc
::hir
::def_id
::{DefId, LOCAL_CRATE}
;
22 use rustc
::middle
::region
;
23 use rustc
::infer
::InferCtxt
;
24 use rustc
::ty
::subst
::Subst
;
25 use rustc
::ty
::{self, Ty, TyCtxt}
;
26 use rustc
::ty
::subst
::{Kind, Substs}
;
27 use syntax
::ast
::{self, LitKind}
;
29 use syntax
::symbol
::Symbol
;
31 use rustc_data_structures
::sync
::Lrc
;
32 use hair
::pattern
::parse_float
;
35 pub struct Cx
<'a
, 'gcx
: 'a
+ 'tcx
, 'tcx
: 'a
> {
36 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
37 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
39 pub root_lint_level
: ast
::NodeId
,
40 pub param_env
: ty
::ParamEnv
<'gcx
>,
42 /// Identity `Substs` for use with const-evaluation.
43 pub identity_substs
: &'gcx Substs
<'gcx
>,
45 pub region_scope_tree
: Lrc
<region
::ScopeTree
>,
46 pub tables
: &'a ty
::TypeckTables
<'gcx
>,
48 /// This is `Constness::Const` if we are compiling a `static`,
49 /// `const`, or the body of a `const fn`.
50 constness
: hir
::Constness
,
52 /// What kind of body is being compiled.
53 pub body_owner_kind
: hir
::BodyOwnerKind
,
55 /// True if this constant/function needs overflow checks.
59 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
60 pub fn new(infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
61 src_id
: ast
::NodeId
) -> Cx
<'a
, 'gcx
, 'tcx
> {
63 let src_def_id
= tcx
.hir
.local_def_id(src_id
);
64 let body_owner_kind
= tcx
.hir
.body_owner_kind(src_id
);
66 let constness
= match body_owner_kind
{
67 hir
::BodyOwnerKind
::Const
|
68 hir
::BodyOwnerKind
::Static(_
) => hir
::Constness
::Const
,
69 hir
::BodyOwnerKind
::Fn
=> hir
::Constness
::NotConst
,
72 let attrs
= tcx
.hir
.attrs(src_id
);
74 // Some functions always have overflow checks enabled,
75 // however, they may not get codegen'd, depending on
76 // the settings for the crate they are codegened in.
77 let mut check_overflow
= attr
::contains_name(attrs
, "rustc_inherit_overflow_checks");
79 // Respect -C overflow-checks.
80 check_overflow
|= tcx
.sess
.overflow_checks();
82 // Constants always need overflow checks.
83 check_overflow
|= constness
== hir
::Constness
::Const
;
85 let lint_level
= lint_level_for_hir_id(tcx
, src_id
);
89 root_lint_level
: lint_level
,
90 param_env
: tcx
.param_env(src_def_id
),
91 identity_substs
: Substs
::identity_for_item(tcx
.global_tcx(), src_def_id
),
92 region_scope_tree
: tcx
.region_scope_tree(src_def_id
),
93 tables
: tcx
.typeck_tables_of(src_def_id
),
102 impl<'a
, 'gcx
, 'tcx
> Cx
<'a
, 'gcx
, 'tcx
> {
103 /// Normalizes `ast` into the appropriate `mirror` type.
104 pub fn mirror
<M
: Mirror
<'tcx
>>(&mut self, ast
: M
) -> M
::Output
{
105 ast
.make_mirror(self)
108 pub fn usize_ty(&mut self) -> Ty
<'tcx
> {
112 pub fn usize_literal(&mut self, value
: u64) -> &'tcx ty
::Const
<'tcx
> {
113 ty
::Const
::from_usize(self.tcx
, value
)
116 pub fn bool_ty(&mut self) -> Ty
<'tcx
> {
120 pub fn unit_ty(&mut self) -> Ty
<'tcx
> {
124 pub fn true_literal(&mut self) -> &'tcx ty
::Const
<'tcx
> {
125 ty
::Const
::from_bool(self.tcx
, true)
128 pub fn false_literal(&mut self) -> &'tcx ty
::Const
<'tcx
> {
129 ty
::Const
::from_bool(self.tcx
, false)
132 // FIXME: Combine with rustc_mir::hair::pattern::lit_to_const
133 pub fn const_eval_literal(
135 lit
: &'tcx ast
::LitKind
,
139 ) -> &'tcx ty
::Const
<'tcx
> {
140 trace
!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit
, ty
, sp
, neg
);
142 let parse_float
= |num
, fty
| -> ConstValue
<'tcx
> {
143 parse_float(num
, fty
, neg
).unwrap_or_else(|_
| {
144 // FIXME(#31407) this is only necessary because float parsing is buggy
145 self.tcx
.sess
.span_fatal(sp
, "could not evaluate float literal (see issue #31407)");
150 let param_ty
= self.param_env
.and(self.tcx
.lift_to_global(&ty
).unwrap());
151 let width
= self.tcx
.layout_of(param_ty
).unwrap().size
;
152 trace
!("trunc {} with size {} and shift {}", n
, width
.bits(), 128 - width
.bits());
153 let shift
= 128 - width
.bits();
154 let result
= (n
<< shift
) >> shift
;
155 trace
!("trunc result: {}", result
);
156 ConstValue
::Scalar(Scalar
::Bits
{
158 size
: width
.bytes() as u8,
162 use rustc
::mir
::interpret
::*;
163 let lit
= match *lit
{
164 LitKind
::Str(ref s
, _
) => {
166 let id
= self.tcx
.allocate_bytes(s
.as_bytes());
167 ConstValue
::new_slice(Scalar
::Ptr(id
.into()), s
.len() as u64, self.tcx
)
169 LitKind
::ByteStr(ref data
) => {
170 let id
= self.tcx
.allocate_bytes(data
);
171 ConstValue
::Scalar(Scalar
::Ptr(id
.into()))
173 LitKind
::Byte(n
) => ConstValue
::Scalar(Scalar
::Bits
{
177 LitKind
::Int(n
, _
) if neg
=> {
179 let n
= n
.overflowing_neg().0;
182 LitKind
::Int(n
, _
) => trunc(n
),
183 LitKind
::Float(n
, fty
) => {
186 LitKind
::FloatUnsuffixed(n
) => {
187 let fty
= match ty
.sty
{
188 ty
::Float(fty
) => fty
,
193 LitKind
::Bool(b
) => ConstValue
::Scalar(Scalar
::from_bool(b
)),
194 LitKind
::Char(c
) => ConstValue
::Scalar(Scalar
::from_char(c
)),
196 ty
::Const
::from_const_value(self.tcx
, lit
, ty
)
199 pub fn pattern_from_hir(&mut self, p
: &hir
::Pat
) -> Pattern
<'tcx
> {
200 let tcx
= self.tcx
.global_tcx();
201 let p
= match tcx
.hir
.get(p
.id
) {
202 Node
::Pat(p
) | Node
::Binding(p
) => p
,
203 node
=> bug
!("pattern became {:?}", node
)
205 Pattern
::from_hir(tcx
,
206 self.param_env
.and(self.identity_substs
),
211 pub fn trait_method(&mut self,
215 params
: &[Kind
<'tcx
>])
216 -> (Ty
<'tcx
>, &'tcx ty
::Const
<'tcx
>) {
217 let method_name
= Symbol
::intern(method_name
);
218 let substs
= self.tcx
.mk_substs_trait(self_ty
, params
);
219 for item
in self.tcx
.associated_items(trait_def_id
) {
220 if item
.kind
== ty
::AssociatedKind
::Method
&& item
.ident
.name
== method_name
{
221 let method_ty
= self.tcx
.type_of(item
.def_id
);
222 let method_ty
= method_ty
.subst(self.tcx
, substs
);
223 return (method_ty
, ty
::Const
::zero_sized(self.tcx
, method_ty
));
227 bug
!("found no method `{}` in `{:?}`", method_name
, trait_def_id
);
230 pub fn all_fields(&mut self, adt_def
: &ty
::AdtDef
, variant_index
: usize) -> Vec
<Field
> {
231 (0..adt_def
.variants
[variant_index
].fields
.len())
236 pub fn needs_drop(&mut self, ty
: Ty
<'tcx
>) -> bool
{
237 let (ty
, param_env
) = self.tcx
.lift_to_global(&(ty
, self.param_env
)).unwrap_or_else(|| {
238 bug
!("MIR: Cx::needs_drop({:?}, {:?}) got \
239 type with inference types/regions",
242 ty
.needs_drop(self.tcx
.global_tcx(), param_env
)
245 fn lint_level_of(&self, node_id
: ast
::NodeId
) -> LintLevel
{
246 let hir_id
= self.tcx
.hir
.definitions().node_to_hir_id(node_id
);
247 let has_lint_level
= self.tcx
.dep_graph
.with_ignore(|| {
248 self.tcx
.lint_levels(LOCAL_CRATE
).lint_level_set(hir_id
).is_some()
252 LintLevel
::Explicit(node_id
)
258 pub fn tcx(&self) -> TyCtxt
<'a
, 'gcx
, 'tcx
> {
262 pub fn tables(&self) -> &'a ty
::TypeckTables
<'gcx
> {
266 pub fn check_overflow(&self) -> bool
{
270 pub fn type_moves_by_default(&self, ty
: Ty
<'tcx
>, span
: Span
) -> bool
{
271 self.infcx
.type_moves_by_default(self.param_env
, ty
, span
)
275 fn lint_level_for_hir_id(tcx
: TyCtxt
, mut id
: ast
::NodeId
) -> ast
::NodeId
{
276 // Right now we insert a `with_ignore` node in the dep graph here to
277 // ignore the fact that `lint_levels` below depends on the entire crate.
278 // For now this'll prevent false positives of recompiling too much when
281 // Once red/green incremental compilation lands we should be able to
282 // remove this because while the crate changes often the lint level map
283 // will change rarely.
284 tcx
.dep_graph
.with_ignore(|| {
285 let sets
= tcx
.lint_levels(LOCAL_CRATE
);
287 let hir_id
= tcx
.hir
.definitions().node_to_hir_id(id
);
288 if sets
.lint_level_set(hir_id
).is_some() {
291 let next
= tcx
.hir
.get_parent_node(id
);
293 bug
!("lint traversal reached the root of the crate");