1 // Copyright 2012 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 use arena
::TypedArena
;
13 use llvm
::{ValueRef, get_params}
;
14 use middle
::def_id
::DefId
;
16 use middle
::subst
::{Subst, Substs}
;
17 use middle
::subst
::VecPerParamSpace
;
29 use trans
::debuginfo
::DebugLoc
;
34 use trans
::monomorphize
;
35 use trans
::type_
::Type
;
36 use trans
::type_of
::*;
37 use middle
::ty
::{self, Ty, TypeFoldable}
;
38 use middle
::ty
::MethodCall
;
42 use syntax
::codemap
::DUMMY_SP
;
46 // drop_glue pointer, size, align.
47 const VTABLE_OFFSET
: usize = 3;
49 /// The main "translation" pass for methods. Generates code
50 /// for non-monomorphized methods only. Other methods will
51 /// be generated once they are invoked with specific type parameters,
52 /// see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
53 pub fn trans_impl(ccx
: &CrateContext
,
55 impl_items
: &[hir
::ImplItem
],
56 generics
: &hir
::Generics
,
58 let _icx
= push_ctxt("meth::trans_impl");
61 debug
!("trans_impl(name={}, id={})", name
, id
);
63 // Both here and below with generic methods, be sure to recurse and look for
64 // items that we need to translate.
65 if !generics
.ty_params
.is_empty() {
69 for impl_item
in impl_items
{
70 match impl_item
.node
{
71 hir
::ImplItemKind
::Method(ref sig
, ref body
) => {
72 if sig
.generics
.ty_params
.is_empty() {
73 let trans_everywhere
= attr
::requests_inline(&impl_item
.attrs
);
74 for (ref ccx
, is_origin
) in ccx
.maybe_iter(trans_everywhere
) {
75 let llfn
= get_item_val(ccx
, impl_item
.id
);
76 let empty_substs
= tcx
.mk_substs(Substs
::trans_empty());
87 if is_origin { OriginalTranslation }
else { InlinedCopy }
);
96 pub fn trans_method_callee
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
97 method_call
: MethodCall
,
98 self_expr
: Option
<&hir
::Expr
>,
99 arg_cleanup_scope
: cleanup
::ScopeId
)
100 -> Callee
<'blk
, 'tcx
> {
101 let _icx
= push_ctxt("meth::trans_method_callee");
103 let method
= bcx
.tcx().tables
.borrow().method_map
[&method_call
];
105 match bcx
.tcx().impl_or_trait_item(method
.def_id
).container() {
106 ty
::ImplContainer(_
) => {
107 debug
!("trans_method_callee: static, {:?}", method
.def_id
);
108 let datum
= callee
::trans_fn_ref(bcx
.ccx(),
110 MethodCallKey(method_call
),
111 bcx
.fcx
.param_substs
);
119 ty
::TraitContainer(trait_def_id
) => {
120 let trait_substs
= method
.substs
.clone().method_to_trait();
121 let trait_substs
= bcx
.tcx().mk_substs(trait_substs
);
122 let trait_ref
= ty
::TraitRef
::new(trait_def_id
, trait_substs
);
124 let trait_ref
= ty
::Binder(bcx
.monomorphize(&trait_ref
));
125 let span
= bcx
.tcx().map
.span(method_call
.expr_id
);
126 debug
!("method_call={:?} trait_ref={:?} trait_ref id={:?} substs={:?}",
131 let origin
= fulfill_obligation(bcx
.ccx(),
134 debug
!("origin = {:?}", origin
);
135 trans_monomorphized_callee(bcx
,
147 pub fn trans_static_method_callee
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
150 expr_id
: ast
::NodeId
,
151 param_substs
: &'tcx subst
::Substs
<'tcx
>)
152 -> Datum
<'tcx
, Rvalue
>
154 let _icx
= push_ctxt("meth::trans_static_method_callee");
157 debug
!("trans_static_method_callee(method_id={:?}, trait_id={}, \
160 tcx
.item_path_str(trait_id
),
163 let mname
= tcx
.item_name(method_id
);
165 debug
!("trans_static_method_callee: method_id={:?}, expr_id={}, \
166 name={}", method_id
, expr_id
, mname
);
168 // Find the substitutions for the fn itself. This includes
169 // type parameters that belong to the trait but also some that
170 // belong to the method:
171 let rcvr_substs
= node_id_substs(ccx
, ExprId(expr_id
), param_substs
);
172 let subst
::SeparateVecsPerParamSpace
{
176 } = rcvr_substs
.types
.split();
178 // Lookup the precise impl being called. To do that, we need to
179 // create a trait reference identifying the self type and other
180 // input type parameters. To create that trait reference, we have
181 // to pick apart the type parameters to identify just those that
182 // pertain to the trait. This is easiest to explain by example:
185 // fn from<U:Foo>(n: U) -> Option<Self>;
188 // let f = <Vec<i32> as Convert>::from::<String>(...)
190 // Here, in this call, which I've written with explicit UFCS
191 // notation, the set of type parameters will be:
193 // rcvr_type: [] <-- nothing declared on the trait itself
194 // rcvr_self: [Vec<i32>] <-- the self type
195 // rcvr_method: [String] <-- method type parameter
197 // So we create a trait reference using the first two,
198 // basically corresponding to `<Vec<i32> as Convert>`.
199 // The remaining type parameters (`rcvr_method`) will be used below.
201 Substs
::erased(VecPerParamSpace
::new(rcvr_type
,
204 let trait_substs
= tcx
.mk_substs(trait_substs
);
205 debug
!("trait_substs={:?}", trait_substs
);
206 let trait_ref
= ty
::Binder(ty
::TraitRef
::new(trait_id
, trait_substs
));
207 let vtbl
= fulfill_obligation(ccx
,
211 // Now that we know which impl is being used, we can dispatch to
212 // the actual function:
214 traits
::VtableImpl(traits
::VtableImplData
{
215 impl_def_id
: impl_did
,
219 assert
!(!impl_substs
.types
.needs_infer());
221 // Create the substitutions that are in scope. This combines
222 // the type parameters from the impl with those declared earlier.
223 // To see what I mean, consider a possible impl:
225 // impl<T> Convert for Vec<T> {
226 // fn from<U:Foo>(n: U) { ... }
229 // Recall that we matched `<Vec<i32> as Convert>`. Trait
230 // resolution will have given us a substitution
231 // containing `impl_substs=[[T=i32],[],[]]` (the type
232 // parameters defined on the impl). We combine
233 // that with the `rcvr_method` from before, which tells us
234 // the type parameters from the *method*, to yield
235 // `callee_substs=[[T=i32],[],[U=String]]`.
236 let subst
::SeparateVecsPerParamSpace
{
240 } = impl_substs
.types
.split();
242 Substs
::erased(VecPerParamSpace
::new(impl_type
,
246 let mth
= tcx
.get_impl_method(impl_did
, callee_substs
, mname
);
247 trans_fn_ref_with_substs(ccx
, mth
.method
.def_id
, ExprId(expr_id
),
251 traits
::VtableObject(ref data
) => {
252 let idx
= traits
::get_vtable_index_of_object_method(tcx
, data
, method_id
);
253 trans_object_shim(ccx
,
254 data
.upcast_trait_ref
.clone(),
259 tcx
.sess
.bug(&format
!("static call to invalid vtable: {:?}",
265 fn trans_monomorphized_callee
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
266 method_call
: MethodCall
,
267 self_expr
: Option
<&hir
::Expr
>,
271 vtable
: traits
::Vtable
<'tcx
, ()>,
272 arg_cleanup_scope
: cleanup
::ScopeId
)
273 -> Callee
<'blk
, 'tcx
> {
274 let _icx
= push_ctxt("meth::trans_monomorphized_callee");
276 traits
::VtableImpl(vtable_impl
) => {
278 let impl_did
= vtable_impl
.impl_def_id
;
279 let mname
= match ccx
.tcx().impl_or_trait_item(method_id
) {
280 ty
::MethodTraitItem(method
) => method
.name
,
282 bcx
.tcx().sess
.bug("can't monomorphize a non-method trait \
286 // create a concatenated set of substitutions which includes
287 // those from the impl and those from the method:
289 combine_impl_and_methods_tps(
290 bcx
, MethodCallKey(method_call
), vtable_impl
.substs
);
292 let mth
= bcx
.tcx().get_impl_method(impl_did
, callee_substs
, mname
);
293 // translate the function
294 let datum
= trans_fn_ref_with_substs(bcx
.ccx(),
296 MethodCallKey(method_call
),
297 bcx
.fcx
.param_substs
,
300 Callee { bcx: bcx, data: Fn(datum.val), ty: datum.ty }
302 traits
::VtableClosure(vtable_closure
) => {
303 // The substitutions should have no type parameters remaining
304 // after passing through fulfill_obligation
305 let trait_closure_kind
= bcx
.tcx().lang_items
.fn_trait_kind(trait_id
).unwrap();
306 let llfn
= closure
::trans_closure_method(bcx
.ccx(),
307 vtable_closure
.closure_def_id
,
308 vtable_closure
.substs
,
313 ty
: monomorphize_type(bcx
, method_ty
)
316 traits
::VtableFnPointer(fn_ty
) => {
317 let trait_closure_kind
= bcx
.tcx().lang_items
.fn_trait_kind(trait_id
).unwrap();
318 let llfn
= trans_fn_pointer_shim(bcx
.ccx(), trait_closure_kind
, fn_ty
);
322 ty
: monomorphize_type(bcx
, method_ty
)
325 traits
::VtableObject(ref data
) => {
326 let idx
= traits
::get_vtable_index_of_object_method(bcx
.tcx(), data
, method_id
);
327 if let Some(self_expr
) = self_expr
{
328 if let ty
::TyBareFn(_
, ref fty
) = monomorphize_type(bcx
, method_ty
).sty
{
329 let ty
= bcx
.tcx().mk_fn(None
, opaque_method_ty(bcx
.tcx(), fty
));
330 return trans_trait_callee(bcx
, ty
, idx
, self_expr
, arg_cleanup_scope
);
333 let datum
= trans_object_shim(bcx
.ccx(),
334 data
.upcast_trait_ref
.clone(),
337 Callee { bcx: bcx, data: Fn(datum.val), ty: datum.ty }
339 traits
::VtableBuiltin(..) |
340 traits
::VtableDefaultImpl(..) |
341 traits
::VtableParam(..) => {
343 &format
!("resolved vtable bad vtable {:?} in trans",
349 /// Creates a concatenated set of substitutions which includes those from the impl and those from
350 /// the method. This are some subtle complications here. Statically, we have a list of type
351 /// parameters like `[T0, T1, T2, M1, M2, M3]` where `Tn` are type parameters that appear on the
352 /// receiver. For example, if the receiver is a method parameter `A` with a bound like
353 /// `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
355 /// The weird part is that the type `A` might now be bound to any other type, such as `foo<X>`.
356 /// In that case, the vector we want is: `[X, M1, M2, M3]`. Therefore, what we do now is to slice
357 /// off the method type parameters and append them to the type parameters from the type that the
358 /// receiver is mapped to.
359 fn combine_impl_and_methods_tps
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
360 node
: ExprOrMethodCall
,
361 rcvr_substs
: subst
::Substs
<'tcx
>)
362 -> subst
::Substs
<'tcx
>
366 let node_substs
= node_id_substs(ccx
, node
, bcx
.fcx
.param_substs
);
368 debug
!("rcvr_substs={:?}", rcvr_substs
);
369 debug
!("node_substs={:?}", node_substs
);
371 // Break apart the type parameters from the node and type
372 // parameters from the receiver.
373 let node_method
= node_substs
.types
.split().fns
;
374 let subst
::SeparateVecsPerParamSpace
{
378 } = rcvr_substs
.types
.clone().split();
379 assert
!(rcvr_method
.is_empty());
381 regions
: subst
::ErasedRegions
,
382 types
: subst
::VecPerParamSpace
::new(rcvr_type
, rcvr_self
, node_method
)
386 /// Create a method callee where the method is coming from a trait object (e.g., Box<Trait> type).
387 /// In this case, we must pull the fn pointer out of the vtable that is packaged up with the
388 /// object. Objects are represented as a pair, so we first evaluate the self expression and then
389 /// extract the self data and vtable out of the pair.
390 fn trans_trait_callee
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
391 opaque_fn_ty
: Ty
<'tcx
>,
393 self_expr
: &hir
::Expr
,
394 arg_cleanup_scope
: cleanup
::ScopeId
)
395 -> Callee
<'blk
, 'tcx
> {
396 let _icx
= push_ctxt("meth::trans_trait_callee");
399 // Translate self_datum and take ownership of the value by
400 // converting to an rvalue.
401 let self_datum
= unpack_datum
!(
402 bcx
, expr
::trans(bcx
, self_expr
));
404 let llval
= if bcx
.fcx
.type_needs_drop(self_datum
.ty
) {
405 let self_datum
= unpack_datum
!(
406 bcx
, self_datum
.to_rvalue_datum(bcx
, "trait_callee"));
408 // Convert to by-ref since `trans_trait_callee_from_llval` wants it
410 let self_datum
= unpack_datum
!(
411 bcx
, self_datum
.to_ref_datum(bcx
));
413 // Arrange cleanup in case something should go wrong before the
414 // actual call occurs.
415 self_datum
.add_clean(bcx
.fcx
, arg_cleanup_scope
)
417 // We don't have to do anything about cleanups for &Trait and &mut Trait.
418 assert
!(self_datum
.kind
.is_by_ref());
422 let llself
= Load(bcx
, expr
::get_dataptr(bcx
, llval
));
423 let llvtable
= Load(bcx
, expr
::get_meta(bcx
, llval
));
424 trans_trait_callee_from_llval(bcx
, opaque_fn_ty
, vtable_index
, llself
, llvtable
)
427 /// Same as `trans_trait_callee()` above, except that it is given a by-ref pointer to the object
429 fn trans_trait_callee_from_llval
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
430 opaque_fn_ty
: Ty
<'tcx
>,
434 -> Callee
<'blk
, 'tcx
> {
435 let _icx
= push_ctxt("meth::trans_trait_callee");
438 // Load the data pointer from the object.
439 debug
!("trans_trait_callee_from_llval(callee_ty={}, vtable_index={}, llself={}, llvtable={})",
442 bcx
.val_to_string(llself
),
443 bcx
.val_to_string(llvtable
));
445 // Replace the self type (&Self or Box<Self>) with an opaque pointer.
446 let mptr
= Load(bcx
, GEPi(bcx
, llvtable
, &[vtable_index
+ VTABLE_OFFSET
]));
447 let llcallee_ty
= type_of_fn_from_ty(ccx
, opaque_fn_ty
);
451 data
: TraitItem(MethodData
{
452 llfn
: PointerCast(bcx
, mptr
, llcallee_ty
.ptr_to()),
453 llself
: PointerCast(bcx
, llself
, Type
::i8p(ccx
)),
459 /// Generate a shim function that allows an object type like `SomeTrait` to
460 /// implement the type `SomeTrait`. Imagine a trait definition:
462 /// trait SomeTrait { fn get(&self) -> i32; ... }
464 /// And a generic bit of code:
466 /// fn foo<T:SomeTrait>(t: &T) {
467 /// let x = SomeTrait::get;
471 /// What is the value of `x` when `foo` is invoked with `T=SomeTrait`?
472 /// The answer is that it is a shim function generated by this routine:
474 /// fn shim(t: &SomeTrait) -> i32 {
475 /// // ... call t.get() virtually ...
478 /// In fact, all virtual calls can be thought of as normal trait calls
479 /// that go through this shim function.
480 pub fn trans_object_shim
<'a
, 'tcx
>(
481 ccx
: &'a CrateContext
<'a
, 'tcx
>,
482 upcast_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
485 -> Datum
<'tcx
, Rvalue
>
487 let _icx
= push_ctxt("trans_object_shim");
490 debug
!("trans_object_shim(upcast_trait_ref={:?}, method_id={:?})",
494 // Upcast to the trait in question and extract out the substitutions.
495 let upcast_trait_ref
= tcx
.erase_late_bound_regions(&upcast_trait_ref
);
496 let object_substs
= upcast_trait_ref
.substs
.clone().erase_regions();
497 debug
!("trans_object_shim: object_substs={:?}", object_substs
);
499 // Lookup the type of this method as declared in the trait and apply substitutions.
500 let method_ty
= match tcx
.impl_or_trait_item(method_id
) {
501 ty
::MethodTraitItem(method
) => method
,
503 tcx
.sess
.bug("can't create a method shim for a non-method item")
506 let fty
= monomorphize
::apply_param_substs(tcx
, &object_substs
, &method_ty
.fty
);
507 let fty
= tcx
.mk_bare_fn(fty
);
508 let method_ty
= opaque_method_ty(tcx
, fty
);
509 debug
!("trans_object_shim: fty={:?} method_ty={:?}", fty
, method_ty
);
512 let shim_fn_ty
= tcx
.mk_fn(None
, fty
);
513 let method_bare_fn_ty
= tcx
.mk_fn(None
, method_ty
);
514 let function_name
= link
::mangle_internal_name_by_type_and_seq(ccx
, shim_fn_ty
, "object_shim");
515 let llfn
= declare
::define_internal_rust_fn(ccx
, &function_name
, shim_fn_ty
);
517 let sig
= ccx
.tcx().erase_late_bound_regions(&fty
.sig
);
518 let sig
= infer
::normalize_associated_type(ccx
.tcx(), &sig
);
520 let empty_substs
= tcx
.mk_substs(Substs
::trans_empty());
521 let (block_arena
, fcx
): (TypedArena
<_
>, FunctionContext
);
522 block_arena
= TypedArena
::new();
523 fcx
= new_fn_ctxt(ccx
,
531 let mut bcx
= init_function(&fcx
, false, sig
.output
);
533 let llargs
= get_params(fcx
.llfn
);
535 let self_idx
= fcx
.arg_offset();
536 let llself
= llargs
[self_idx
];
537 let llvtable
= llargs
[self_idx
+ 1];
539 debug
!("trans_object_shim: llself={}, llvtable={}",
540 bcx
.val_to_string(llself
), bcx
.val_to_string(llvtable
));
542 assert
!(!fcx
.needs_ret_allocas
);
545 fcx
.llretslotptr
.get().map(
546 |_
| expr
::SaveIn(fcx
.get_ret_slot(bcx
, sig
.output
, "ret_slot")));
548 debug
!("trans_object_shim: method_offset_in_vtable={}",
551 bcx
= trans_call_inner(bcx
,
553 |bcx
, _
| trans_trait_callee_from_llval(bcx
,
557 ArgVals(&llargs
[(self_idx
+ 2)..]),
560 finish_fn(&fcx
, bcx
, sig
.output
, DebugLoc
::None
);
562 immediate_rvalue(llfn
, shim_fn_ty
)
565 /// Creates a returns a dynamic vtable for the given type and vtable origin.
566 /// This is used only for objects.
568 /// The `trait_ref` encodes the erased self type. Hence if we are
569 /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
570 /// `trait_ref` would map `T:Trait`.
571 pub fn get_vtable
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
572 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
573 param_substs
: &'tcx subst
::Substs
<'tcx
>)
577 let _icx
= push_ctxt("meth::get_vtable");
579 debug
!("get_vtable(trait_ref={:?})", trait_ref
);
582 match ccx
.vtables().borrow().get(&trait_ref
) {
583 Some(&val
) => { return val }
587 // Not in the cache. Build it.
588 let methods
= traits
::supertraits(tcx
, trait_ref
.clone()).flat_map(|trait_ref
| {
589 let vtable
= fulfill_obligation(ccx
, DUMMY_SP
, trait_ref
.clone());
591 // Should default trait error here?
592 traits
::VtableDefaultImpl(_
) |
593 traits
::VtableBuiltin(_
) => {
594 Vec
::new().into_iter()
597 traits
::VtableImplData
{
601 emit_vtable_methods(ccx
, id
, substs
, param_substs
).into_iter()
603 traits
::VtableClosure(
604 traits
::VtableClosureData
{
608 let trait_closure_kind
= tcx
.lang_items
.fn_trait_kind(trait_ref
.def_id()).unwrap();
609 let llfn
= closure
::trans_closure_method(ccx
,
613 vec
![llfn
].into_iter()
615 traits
::VtableFnPointer(bare_fn_ty
) => {
616 let trait_closure_kind
= tcx
.lang_items
.fn_trait_kind(trait_ref
.def_id()).unwrap();
617 vec
![trans_fn_pointer_shim(ccx
, trait_closure_kind
, bare_fn_ty
)].into_iter()
619 traits
::VtableObject(ref data
) => {
620 // this would imply that the Self type being erased is
621 // an object type; this cannot happen because we
622 // cannot cast an unsized type into a trait object
624 &format
!("cannot get vtable for an object type: {:?}",
627 traits
::VtableParam(..) => {
629 &format
!("resolved vtable for {:?} to bad vtable {:?} in trans",
636 let size_ty
= sizing_type_of(ccx
, trait_ref
.self_ty());
637 let size
= machine
::llsize_of_alloc(ccx
, size_ty
);
638 let align
= align_of(ccx
, trait_ref
.self_ty());
640 let components
: Vec
<_
> = vec
![
641 // Generate a destructor for the vtable.
642 glue
::get_drop_glue(ccx
, trait_ref
.self_ty()),
645 ].into_iter().chain(methods
).collect();
647 let vtable_const
= C_struct(ccx
, &components
, false);
648 let align
= machine
::llalign_of_pref(ccx
, val_ty(vtable_const
));
649 let vtable
= consts
::addr_of(ccx
, vtable_const
, align
, "vtable");
651 ccx
.vtables().borrow_mut().insert(trait_ref
, vtable
);
655 fn emit_vtable_methods
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
657 substs
: subst
::Substs
<'tcx
>,
658 param_substs
: &'tcx subst
::Substs
<'tcx
>)
663 debug
!("emit_vtable_methods(impl_id={:?}, substs={:?}, param_substs={:?})",
668 let trt_id
= match tcx
.impl_trait_ref(impl_id
) {
669 Some(t_id
) => t_id
.def_id
,
670 None
=> ccx
.sess().bug("make_impl_vtable: don't know how to \
671 make a vtable for a type impl!")
674 tcx
.populate_implementations_for_trait_if_necessary(trt_id
);
676 let nullptr
= C_null(Type
::nil(ccx
).ptr_to());
677 let trait_item_def_ids
= tcx
.trait_item_def_ids(trt_id
);
681 // Filter out non-method items.
682 .filter_map(|item_def_id
| {
684 ty
::MethodTraitItemId(def_id
) => Some(def_id
),
689 // Now produce pointers for each remaining method. If the
690 // method could never be called from this object, just supply
692 .map(|trait_method_def_id
| {
693 debug
!("emit_vtable_methods: trait_method_def_id={:?}",
694 trait_method_def_id
);
696 let trait_method_type
= match tcx
.impl_or_trait_item(trait_method_def_id
) {
697 ty
::MethodTraitItem(m
) => m
,
698 _
=> ccx
.sess().bug("should be a method, not other assoc item"),
700 let name
= trait_method_type
.name
;
702 // Some methods cannot be called on an object; skip those.
703 if !traits
::is_vtable_safe_method(tcx
, trt_id
, &trait_method_type
) {
704 debug
!("emit_vtable_methods: not vtable safe");
708 debug
!("emit_vtable_methods: trait_method_type={:?}",
711 // The substitutions we have are on the impl, so we grab
712 // the method type from the impl to substitute into.
713 let mth
= tcx
.get_impl_method(impl_id
, substs
.clone(), name
);
715 debug
!("emit_vtable_methods: mth={:?}", mth
);
717 // If this is a default method, it's possible that it
718 // relies on where clauses that do not hold for this
719 // particular set of type parameters. Note that this
720 // method could then never be called, so we do not want to
721 // try and trans it, in that case. Issue #23435.
723 let predicates
= mth
.method
.predicates
.predicates
.subst(tcx
, &mth
.substs
);
724 if !normalize_and_test_predicates(ccx
, predicates
.into_vec()) {
725 debug
!("emit_vtable_methods: predicates do not hold");
730 trans_fn_ref_with_substs(ccx
,
739 /// Replace the self type (&Self or Box<Self>) with an opaque pointer.
740 fn opaque_method_ty
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>, method_ty
: &ty
::BareFnTy
<'tcx
>)
741 -> &'tcx ty
::BareFnTy
<'tcx
> {
742 let mut inputs
= method_ty
.sig
.0.inputs
.clone();
743 inputs
[0] = tcx
.mk_mut_ptr(tcx
.mk_mach_int(ast
::TyI8
));
745 tcx
.mk_bare_fn(ty
::BareFnTy
{
746 unsafety
: method_ty
.unsafety
,
748 sig
: ty
::Binder(ty
::FnSig
{
750 output
: method_ty
.sig
.0.output
,
751 variadic
: method_ty
.sig
.0.variadic
,