]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/trans/mir/did.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc_trans / trans / mir / did.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.
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;
19 use rustc::middle::traits;
20 use rustc::mir::repr::ItemKind;
21 use trans::common::{BlockAndBuilder, fulfill_obligation};
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,
35 bcx: &BlockAndBuilder<'bcx, 'tcx>,
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),
48 ty::TraitContainer(tdid) => self.trans_trait_method(bcx, ty, did, tdid, substs)
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.
56 let d = bcx.with_block(|bcx| {
57 expr::trans(bcx, expr)
58 });
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,
71 bcx: &BlockAndBuilder<'bcx, 'tcx>,
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
102 /// Translates references to trait methods.
103 ///
104 /// This is an adaptation of meth::trans_static_method_callee
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> {
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();
120 let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id));
121 let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref);
122 match vtbl {
123 traits::VtableImpl(traits::VtableImplData {
124 impl_def_id, substs: impl_substs, ..
125 }) => {
126 assert!(!impl_substs.types.needs_infer());
127
128 let mname = tcx.item_name(method_id);
129
130 let callee_substs = impl_substs.with_method_from(substs);
131 let mth = tcx.get_impl_method(impl_def_id, callee_substs, mname);
132 let mth_substs = tcx.mk_substs(mth.substs);
133 self.trans_fn_ref(bcx, ty, mth_substs, mth.method.def_id)
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 }