]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
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. | |
4 | // | |
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. | |
10 | ||
b039eaaf SL |
11 | /*! |
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 | |
15 | * work. | |
16 | */ | |
17 | ||
e9174d1e | 18 | use hair::*; |
92a42be0 | 19 | use rustc::mir::repr::*; |
b039eaaf | 20 | |
54a0048b SL |
21 | use rustc::middle::const_val::ConstVal; |
22 | use rustc_const_eval as const_eval; | |
23 | use rustc::hir::def_id::DefId; | |
24 | use rustc::infer::InferCtxt; | |
25 | use rustc::ty::subst::{Subst, Substs}; | |
26 | use rustc::ty::{self, Ty, TyCtxt}; | |
92a42be0 | 27 | use syntax::parse::token; |
54a0048b SL |
28 | use rustc::hir; |
29 | use rustc_const_math::{ConstInt, ConstUsize}; | |
e9174d1e SL |
30 | |
31 | #[derive(Copy, Clone)] | |
b039eaaf | 32 | pub struct Cx<'a, 'tcx: 'a> { |
54a0048b | 33 | tcx: &'a TyCtxt<'tcx>, |
b039eaaf | 34 | infcx: &'a InferCtxt<'a, 'tcx>, |
e9174d1e SL |
35 | } |
36 | ||
37 | impl<'a,'tcx> Cx<'a,'tcx> { | |
b039eaaf SL |
38 | pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Cx<'a, 'tcx> { |
39 | Cx { | |
40 | tcx: infcx.tcx, | |
41 | infcx: infcx, | |
42 | } | |
e9174d1e SL |
43 | } |
44 | } | |
45 | ||
b039eaaf SL |
46 | impl<'a,'tcx:'a> Cx<'a, 'tcx> { |
47 | /// Normalizes `ast` into the appropriate `mirror` type. | |
48 | pub fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output { | |
49 | ast.make_mirror(self) | |
50 | } | |
51 | ||
b039eaaf | 52 | pub fn usize_ty(&mut self) -> Ty<'tcx> { |
e9174d1e SL |
53 | self.tcx.types.usize |
54 | } | |
55 | ||
54a0048b SL |
56 | pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> { |
57 | match ConstUsize::new(value, self.tcx.sess.target.uint_type) { | |
58 | Ok(val) => Literal::Value { value: ConstVal::Integral(ConstInt::Usize(val))}, | |
59 | Err(_) => bug!("usize literal out of range for target"), | |
60 | } | |
b039eaaf SL |
61 | } |
62 | ||
63 | pub fn bool_ty(&mut self) -> Ty<'tcx> { | |
e9174d1e SL |
64 | self.tcx.types.bool |
65 | } | |
66 | ||
7453a54e SL |
67 | pub fn unit_ty(&mut self) -> Ty<'tcx> { |
68 | self.tcx.mk_nil() | |
69 | } | |
70 | ||
9cc50fc6 SL |
71 | pub fn str_literal(&mut self, value: token::InternedString) -> Literal<'tcx> { |
72 | Literal::Value { value: ConstVal::Str(value) } | |
73 | } | |
74 | ||
b039eaaf SL |
75 | pub fn true_literal(&mut self) -> Literal<'tcx> { |
76 | Literal::Value { value: ConstVal::Bool(true) } | |
77 | } | |
78 | ||
79 | pub fn false_literal(&mut self) -> Literal<'tcx> { | |
80 | Literal::Value { value: ConstVal::Bool(false) } | |
81 | } | |
82 | ||
92a42be0 SL |
83 | pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> { |
84 | Literal::Value { value: const_eval::eval_const_expr(self.tcx, e) } | |
85 | } | |
86 | ||
9cc50fc6 SL |
87 | pub fn try_const_eval_literal(&mut self, e: &hir::Expr) -> Option<Literal<'tcx>> { |
88 | let hint = const_eval::EvalHint::ExprTypeChecked; | |
54a0048b SL |
89 | const_eval::eval_const_expr_partial(self.tcx, e, hint, None).ok().and_then(|v| { |
90 | match v { | |
91 | // All of these contain local IDs, unsuitable for storing in MIR. | |
92 | ConstVal::Struct(_) | ConstVal::Tuple(_) | | |
93 | ConstVal::Array(..) | ConstVal::Repeat(..) | | |
94 | ConstVal::Function(_) => None, | |
95 | ||
96 | _ => Some(Literal::Value { value: v }) | |
97 | } | |
98 | }) | |
99 | } | |
100 | ||
101 | pub fn trait_method(&mut self, | |
102 | trait_def_id: DefId, | |
103 | method_name: &str, | |
104 | self_ty: Ty<'tcx>, | |
105 | params: Vec<Ty<'tcx>>) | |
106 | -> (Ty<'tcx>, Literal<'tcx>) { | |
107 | let method_name = token::intern(method_name); | |
108 | let substs = Substs::new_trait(params, vec![], self_ty); | |
109 | for trait_item in self.tcx.trait_items(trait_def_id).iter() { | |
110 | match *trait_item { | |
111 | ty::ImplOrTraitItem::MethodTraitItem(ref method) => { | |
112 | if method.name == method_name { | |
113 | let method_ty = self.tcx.lookup_item_type(method.def_id); | |
114 | let method_ty = method_ty.ty.subst(self.tcx, &substs); | |
115 | return (method_ty, Literal::Item { | |
116 | def_id: method.def_id, | |
117 | substs: self.tcx.mk_substs(substs), | |
118 | }); | |
119 | } | |
120 | } | |
121 | ty::ImplOrTraitItem::ConstTraitItem(..) | | |
122 | ty::ImplOrTraitItem::TypeTraitItem(..) => {} | |
123 | } | |
124 | } | |
125 | ||
126 | bug!("found no method `{}` in `{:?}`", method_name, trait_def_id); | |
e9174d1e SL |
127 | } |
128 | ||
b039eaaf | 129 | pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize { |
e9174d1e SL |
130 | adt_def.variants.len() |
131 | } | |
132 | ||
92a42be0 SL |
133 | pub fn all_fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field> { |
134 | (0..adt_def.variants[variant_index].fields.len()) | |
135 | .map(Field::new) | |
e9174d1e SL |
136 | .collect() |
137 | } | |
138 | ||
9cc50fc6 SL |
139 | pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool { |
140 | self.tcx.type_needs_drop_given_env(ty, &self.infcx.parameter_environment) | |
e9174d1e SL |
141 | } |
142 | ||
54a0048b | 143 | pub fn tcx(&self) -> &'a TyCtxt<'tcx> { |
b039eaaf SL |
144 | self.tcx |
145 | } | |
e9174d1e SL |
146 | } |
147 | ||
148 | mod block; | |
149 | mod expr; | |
150 | mod pattern; | |
151 | mod to_ref; |