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 //! Code for translating references to other items (DefIds).
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}
;
25 use trans
::monomorphize
;
29 use super::MirContext
;
30 use super::operand
::{OperandRef, OperandValue}
;
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
>,
38 substs
: &'tcx Substs
<'tcx
>,
41 debug
!("trans_item_ref(ty={:?}, kind={:?}, substs={:?}, did={})",
42 ty
, kind
, substs
, bcx
.tcx().item_path_str(did
));
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
)
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
)
59 OperandRef
::from_rvalue_datum(d
.datum
.to_rvalue_datum(d
.bcx
, "").datum
)
64 /// Translates references to a function-like items.
66 /// That includes regular functions, non-static methods, struct and enum variant constructors,
67 /// closures and possibly more.
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
>,
73 substs
: &'tcx Substs
<'tcx
>,
76 debug
!("trans_fn_ref(ty={:?}, substs={:?}, did={})",
77 ty
, substs
, bcx
.tcx().item_path_str(did
));
79 let did
= inline
::maybe_instantiate_inline(bcx
.ccx(), did
);
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
86 val
: OperandValue
::Immediate(val
)
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
)
92 base
::trans_external_path(bcx
.ccx(), did
, ty
)
94 // FIXME: cast fnptr to proper type if necessary
97 val
: OperandValue
::Immediate(val
)
102 /// Translates references to trait methods.
104 /// This is an adaptation of meth::trans_static_method_callee
105 pub fn trans_trait_method(&mut self,
106 bcx
: &BlockAndBuilder
<'bcx
, 'tcx
>,
110 substs
: &'tcx Substs
<'tcx
>)
111 -> OperandRef
<'tcx
> {
112 debug
!("trans_static_method(ty={:?}, method={}, trait={}, substs={:?})",
114 bcx
.tcx().item_path_str(method_id
),
115 bcx
.tcx().item_path_str(trait_id
),
120 let trait_ref
= ty
::Binder(substs
.to_trait_ref(tcx
, trait_id
));
121 let vtbl
= fulfill_obligation(ccx
, DUMMY_SP
, trait_ref
);
123 traits
::VtableImpl(traits
::VtableImplData
{
124 impl_def_id
, substs
: impl_substs
, ..
126 assert
!(!impl_substs
.types
.needs_infer());
128 let mname
= tcx
.item_name(method_id
);
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
)
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(),
143 val
: OperandValue
::Immediate(llfn
)
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
)
153 tcx
.sess
.bug(&format
!("static call to invalid vtable: {:?}", vtbl
));
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
) {
162 None
=> { return false; }
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()
168 map
::NodeStructCtor(_
) => true,