]>
Commit | Line | Data |
---|---|---|
9cc50fc6 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 | ||
11 | //! Code for translating references to other items (DefIds). | |
12 | ||
13 | use syntax::codemap::DUMMY_SP; | |
14 | use rustc::front::map; | |
15 | use rustc::middle::ty::{self, Ty, TypeFoldable}; | |
16 | use rustc::middle::subst::Substs; | |
17 | use rustc::middle::const_eval; | |
18 | use rustc::middle::def_id::DefId; | |
9cc50fc6 SL |
19 | use rustc::middle::traits; |
20 | use rustc::mir::repr::ItemKind; | |
7453a54e | 21 | use trans::common::{BlockAndBuilder, fulfill_obligation}; |
9cc50fc6 SL |
22 | use trans::base; |
23 | use trans::closure; | |
24 | use trans::expr; | |
25 | use trans::monomorphize; | |
26 | use trans::meth; | |
27 | use trans::inline; | |
28 | ||
29 | use super::MirContext; | |
30 | use super::operand::{OperandRef, OperandValue}; | |
31 | ||
32 | impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { | |
33 | /// Translate reference to item. | |
34 | pub fn trans_item_ref(&mut self, | |
7453a54e | 35 | bcx: &BlockAndBuilder<'bcx, 'tcx>, |
9cc50fc6 SL |
36 | ty: Ty<'tcx>, |
37 | kind: ItemKind, | |
38 | substs: &'tcx Substs<'tcx>, | |
39 | did: DefId) | |
40 | -> OperandRef<'tcx> { | |
41 | debug!("trans_item_ref(ty={:?}, kind={:?}, substs={:?}, did={})", | |
42 | ty, kind, substs, bcx.tcx().item_path_str(did)); | |
43 | ||
44 | match kind { | |
45 | ItemKind::Function => self.trans_fn_ref(bcx, ty, substs, did), | |
46 | ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() { | |
47 | ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did), | |
7453a54e | 48 | ty::TraitContainer(tdid) => self.trans_trait_method(bcx, ty, did, tdid, substs) |
9cc50fc6 SL |
49 | }, |
50 | ItemKind::Constant => { | |
51 | let did = inline::maybe_instantiate_inline(bcx.ccx(), did); | |
52 | let expr = const_eval::lookup_const_by_id(bcx.tcx(), did, None, Some(substs)) | |
53 | .expect("def was const, but lookup_const_by_id failed"); | |
54 | // FIXME: this is falling back to translating from HIR. This is not easy to fix, | |
55 | // because we would have somehow adapt const_eval to work on MIR rather than HIR. | |
7453a54e SL |
56 | let d = bcx.with_block(|bcx| { |
57 | expr::trans(bcx, expr) | |
58 | }); | |
9cc50fc6 SL |
59 | OperandRef::from_rvalue_datum(d.datum.to_rvalue_datum(d.bcx, "").datum) |
60 | } | |
61 | } | |
62 | } | |
63 | ||
64 | /// Translates references to a function-like items. | |
65 | /// | |
66 | /// That includes regular functions, non-static methods, struct and enum variant constructors, | |
67 | /// closures and possibly more. | |
68 | /// | |
69 | /// This is an adaptation of callee::trans_fn_ref_with_substs. | |
70 | pub fn trans_fn_ref(&mut self, | |
7453a54e | 71 | bcx: &BlockAndBuilder<'bcx, 'tcx>, |
9cc50fc6 SL |
72 | ty: Ty<'tcx>, |
73 | substs: &'tcx Substs<'tcx>, | |
74 | did: DefId) | |
75 | -> OperandRef<'tcx> { | |
76 | debug!("trans_fn_ref(ty={:?}, substs={:?}, did={})", | |
77 | ty, substs, bcx.tcx().item_path_str(did)); | |
78 | ||
79 | let did = inline::maybe_instantiate_inline(bcx.ccx(), did); | |
80 | ||
81 | if !substs.types.is_empty() || is_named_tuple_constructor(bcx.tcx(), did) { | |
82 | let (val, fn_ty, _) = monomorphize::monomorphic_fn(bcx.ccx(), did, substs, None); | |
83 | // FIXME: cast fnptr to proper type if necessary | |
84 | OperandRef { | |
85 | ty: fn_ty, | |
86 | val: OperandValue::Immediate(val) | |
87 | } | |
88 | } else { | |
89 | let val = if let Some(node_id) = bcx.tcx().map.as_local_node_id(did) { | |
90 | base::get_item_val(bcx.ccx(), node_id) | |
91 | } else { | |
92 | base::trans_external_path(bcx.ccx(), did, ty) | |
93 | }; | |
94 | // FIXME: cast fnptr to proper type if necessary | |
95 | OperandRef { | |
96 | ty: ty, | |
97 | val: OperandValue::Immediate(val) | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
7453a54e | 102 | /// Translates references to trait methods. |
9cc50fc6 SL |
103 | /// |
104 | /// This is an adaptation of meth::trans_static_method_callee | |
7453a54e SL |
105 | pub fn trans_trait_method(&mut self, |
106 | bcx: &BlockAndBuilder<'bcx, 'tcx>, | |
107 | ty: Ty<'tcx>, | |
108 | method_id: DefId, | |
109 | trait_id: DefId, | |
110 | substs: &'tcx Substs<'tcx>) | |
111 | -> OperandRef<'tcx> { | |
9cc50fc6 SL |
112 | debug!("trans_static_method(ty={:?}, method={}, trait={}, substs={:?})", |
113 | ty, | |
114 | bcx.tcx().item_path_str(method_id), | |
115 | bcx.tcx().item_path_str(trait_id), | |
116 | substs); | |
117 | ||
118 | let ccx = bcx.ccx(); | |
119 | let tcx = bcx.tcx(); | |
7453a54e | 120 | let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id)); |
9cc50fc6 SL |
121 | let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref); |
122 | match vtbl { | |
7453a54e SL |
123 | traits::VtableImpl(traits::VtableImplData { |
124 | impl_def_id, substs: impl_substs, .. | |
125 | }) => { | |
126 | assert!(!impl_substs.types.needs_infer()); | |
9cc50fc6 SL |
127 | |
128 | let mname = tcx.item_name(method_id); | |
129 | ||
7453a54e | 130 | let callee_substs = impl_substs.with_method_from(substs); |
9cc50fc6 | 131 | let mth = tcx.get_impl_method(impl_def_id, callee_substs, mname); |
7453a54e SL |
132 | let mth_substs = tcx.mk_substs(mth.substs); |
133 | self.trans_fn_ref(bcx, ty, mth_substs, mth.method.def_id) | |
9cc50fc6 SL |
134 | }, |
135 | traits::VtableClosure(data) => { | |
136 | let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap(); | |
137 | let llfn = closure::trans_closure_method(bcx.ccx(), | |
138 | data.closure_def_id, | |
139 | data.substs, | |
140 | trait_closure_kind); | |
141 | OperandRef { | |
142 | ty: ty, | |
143 | val: OperandValue::Immediate(llfn) | |
144 | } | |
145 | }, | |
146 | traits::VtableObject(ref data) => { | |
147 | let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id); | |
148 | OperandRef::from_rvalue_datum( | |
149 | meth::trans_object_shim(ccx, data.upcast_trait_ref.clone(), method_id, idx) | |
150 | ) | |
151 | } | |
152 | _ => { | |
153 | tcx.sess.bug(&format!("static call to invalid vtable: {:?}", vtbl)); | |
154 | } | |
155 | } | |
156 | } | |
157 | } | |
158 | ||
159 | fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool { | |
160 | let node_id = match tcx.map.as_local_node_id(def_id) { | |
161 | Some(n) => n, | |
162 | None => { return false; } | |
163 | }; | |
164 | match tcx.map.find(node_id).expect("local item should be in ast map") { | |
165 | map::NodeVariant(v) => { | |
166 | v.node.data.is_tuple() | |
167 | } | |
168 | map::NodeStructCtor(_) => true, | |
169 | _ => false | |
170 | } | |
171 | } |