]> git.proxmox.com Git - rustc.git/blob - src/librustc_typeck/check/method/confirm.rs
Imported Upstream version 1.1.0+dfsg1
[rustc.git] / src / librustc_typeck / check / method / confirm.rs
1 // Copyright 2014 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 use super::probe;
12
13 use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
14 use check::UnresolvedTypeAction;
15 use middle::mem_categorization::Typer;
16 use middle::subst::{self};
17 use middle::traits;
18 use middle::ty::{self, Ty};
19 use middle::ty::{MethodCall, MethodCallee, MethodObject, MethodOrigin,
20 MethodParam, MethodStatic, MethodTraitObject, MethodTypeParam};
21 use middle::ty_fold::TypeFoldable;
22 use middle::infer;
23 use middle::infer::InferCtxt;
24 use syntax::ast;
25 use syntax::codemap::Span;
26 use std::iter::repeat;
27 use util::ppaux::Repr;
28
29 struct ConfirmContext<'a, 'tcx:'a> {
30 fcx: &'a FnCtxt<'a, 'tcx>,
31 span: Span,
32 self_expr: &'tcx ast::Expr,
33 call_expr: &'tcx ast::Expr,
34 }
35
36 struct InstantiatedMethodSig<'tcx> {
37 /// Function signature of the method being invoked. The 0th
38 /// argument is the receiver.
39 method_sig: ty::FnSig<'tcx>,
40
41 /// Substitutions for all types/early-bound-regions declared on
42 /// the method.
43 all_substs: subst::Substs<'tcx>,
44
45 /// Generic bounds on the method's parameters which must be added
46 /// as pending obligations.
47 method_predicates: ty::InstantiatedPredicates<'tcx>,
48 }
49
50 pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
51 span: Span,
52 self_expr: &'tcx ast::Expr,
53 call_expr: &'tcx ast::Expr,
54 unadjusted_self_ty: Ty<'tcx>,
55 pick: probe::Pick<'tcx>,
56 supplied_method_types: Vec<Ty<'tcx>>)
57 -> MethodCallee<'tcx>
58 {
59 debug!("confirm(unadjusted_self_ty={}, pick={}, supplied_method_types={})",
60 unadjusted_self_ty.repr(fcx.tcx()),
61 pick.repr(fcx.tcx()),
62 supplied_method_types.repr(fcx.tcx()));
63
64 let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr, call_expr);
65 confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types)
66 }
67
68 impl<'a,'tcx> ConfirmContext<'a,'tcx> {
69 fn new(fcx: &'a FnCtxt<'a, 'tcx>,
70 span: Span,
71 self_expr: &'tcx ast::Expr,
72 call_expr: &'tcx ast::Expr)
73 -> ConfirmContext<'a, 'tcx>
74 {
75 ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
76 }
77
78 fn confirm(&mut self,
79 unadjusted_self_ty: Ty<'tcx>,
80 pick: probe::Pick<'tcx>,
81 supplied_method_types: Vec<Ty<'tcx>>)
82 -> MethodCallee<'tcx>
83 {
84 // Adjust the self expression the user provided and obtain the adjusted type.
85 let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
86
87 // Make sure nobody calls `drop()` explicitly.
88 self.enforce_illegal_method_limitations(&pick);
89
90 // Create substitutions for the method's type parameters.
91 let (rcvr_substs, method_origin) =
92 self.fresh_receiver_substs(self_ty, &pick);
93 let (method_types, method_regions) =
94 self.instantiate_method_substs(&pick, supplied_method_types);
95 let all_substs = rcvr_substs.with_method(method_types, method_regions);
96 debug!("all_substs={}", all_substs.repr(self.tcx()));
97
98 // Create the final signature for the method, replacing late-bound regions.
99 let InstantiatedMethodSig {
100 method_sig, all_substs, method_predicates
101 } = self.instantiate_method_sig(&pick, all_substs);
102 let method_self_ty = method_sig.inputs[0];
103
104 // Unify the (adjusted) self type with what the method expects.
105 self.unify_receivers(self_ty, method_self_ty);
106
107 // Add any trait/regions obligations specified on the method's type parameters.
108 self.add_obligations(&pick, &all_substs, &method_predicates);
109
110 // Create the final `MethodCallee`.
111 let method_ty = pick.item.as_opt_method().unwrap();
112 let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy {
113 sig: ty::Binder(method_sig),
114 unsafety: method_ty.fty.unsafety,
115 abi: method_ty.fty.abi.clone(),
116 }));
117 let callee = MethodCallee {
118 origin: method_origin,
119 ty: fty,
120 substs: all_substs
121 };
122
123 // If this is an `&mut self` method, bias the receiver
124 // expression towards mutability (this will switch
125 // e.g. `Deref` to `DerefMut` in overloaded derefs and so on).
126 self.fixup_derefs_on_method_receiver_if_necessary(&callee);
127
128 callee
129 }
130
131 ///////////////////////////////////////////////////////////////////////////
132 // ADJUSTMENTS
133
134 fn adjust_self_ty(&mut self,
135 unadjusted_self_ty: Ty<'tcx>,
136 pick: &probe::Pick<'tcx>)
137 -> Ty<'tcx>
138 {
139 let (autoref, unsize) = if let Some(mutbl) = pick.autoref {
140 let region = self.infcx().next_region_var(infer::Autoref(self.span));
141 let autoref = ty::AutoPtr(self.tcx().mk_region(region), mutbl);
142 (Some(autoref), pick.unsize.map(|target| {
143 ty::adjust_ty_for_autoref(self.tcx(), target, Some(autoref))
144 }))
145 } else {
146 // No unsizing should be performed without autoref (at
147 // least during method dispach). This is because we
148 // currently only unsize `[T;N]` to `[T]`, and naturally
149 // that must occur being a reference.
150 assert!(pick.unsize.is_none());
151 (None, None)
152 };
153
154 // Commit the autoderefs by calling `autoderef again, but this
155 // time writing the results into the various tables.
156 let (autoderefd_ty, n, result) = check::autoderef(self.fcx,
157 self.span,
158 unadjusted_self_ty,
159 Some(self.self_expr),
160 UnresolvedTypeAction::Error,
161 NoPreference,
162 |_, n| {
163 if n == pick.autoderefs {
164 Some(())
165 } else {
166 None
167 }
168 });
169 assert_eq!(n, pick.autoderefs);
170 assert_eq!(result, Some(()));
171
172 // Write out the final adjustment.
173 self.fcx.write_adjustment(self.self_expr.id,
174 ty::AdjustDerefRef(ty::AutoDerefRef {
175 autoderefs: pick.autoderefs,
176 autoref: autoref,
177 unsize: unsize
178 }));
179
180 if let Some(target) = unsize {
181 target
182 } else {
183 ty::adjust_ty_for_autoref(self.tcx(), autoderefd_ty, autoref)
184 }
185 }
186
187 ///////////////////////////////////////////////////////////////////////////
188 //
189
190 /// Returns a set of substitutions for the method *receiver* where all type and region
191 /// parameters are instantiated with fresh variables. This substitution does not include any
192 /// parameters declared on the method itself.
193 ///
194 /// Note that this substitution may include late-bound regions from the impl level. If so,
195 /// these are instantiated later in the `instantiate_method_sig` routine.
196 fn fresh_receiver_substs(&mut self,
197 self_ty: Ty<'tcx>,
198 pick: &probe::Pick<'tcx>)
199 -> (subst::Substs<'tcx>, MethodOrigin<'tcx>)
200 {
201 match pick.kind {
202 probe::InherentImplPick(impl_def_id) => {
203 assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(),
204 "impl {:?} is not an inherent impl", impl_def_id);
205 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
206
207 (impl_polytype.substs, MethodStatic(pick.item.def_id()))
208 }
209
210 probe::ObjectPick(trait_def_id, method_num, vtable_index) => {
211 self.extract_trait_ref(self_ty, |this, object_ty, data| {
212 // The object data has no entry for the Self
213 // Type. For the purposes of this method call, we
214 // substitute the object type itself. This
215 // wouldn't be a sound substitution in all cases,
216 // since each instance of the object type is a
217 // different existential and hence could match
218 // distinct types (e.g., if `Self` appeared as an
219 // argument type), but those cases have already
220 // been ruled out when we deemed the trait to be
221 // "object safe".
222 let original_poly_trait_ref =
223 data.principal_trait_ref_with_self_ty(this.tcx(), object_ty);
224 let upcast_poly_trait_ref =
225 this.upcast(original_poly_trait_ref.clone(), trait_def_id);
226 let upcast_trait_ref =
227 this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
228 debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}",
229 original_poly_trait_ref.repr(this.tcx()),
230 upcast_trait_ref.repr(this.tcx()),
231 trait_def_id.repr(this.tcx()));
232 let substs = upcast_trait_ref.substs.clone();
233 let origin = MethodTraitObject(MethodObject {
234 trait_ref: upcast_trait_ref,
235 object_trait_id: trait_def_id,
236 method_num: method_num,
237 vtable_index: vtable_index,
238 });
239 (substs, origin)
240 })
241 }
242
243 probe::ExtensionImplPick(impl_def_id, method_num) => {
244 // The method being invoked is the method as defined on the trait,
245 // so return the substitutions from the trait. Consider:
246 //
247 // impl<A,B,C> Trait<A,B> for Foo<C> { ... }
248 //
249 // If we instantiate A, B, and C with $A, $B, and $C
250 // respectively, then we want to return the type
251 // parameters from the trait ([$A,$B]), not those from
252 // the impl ([$A,$B,$C]) not the receiver type ([$C]).
253 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
254 let impl_trait_ref =
255 self.fcx.instantiate_type_scheme(
256 self.span,
257 &impl_polytype.substs,
258 &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
259 let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
260 method_num: method_num,
261 impl_def_id: Some(impl_def_id) });
262 (impl_trait_ref.substs.clone(), origin)
263 }
264
265 probe::TraitPick(trait_def_id, method_num) => {
266 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
267
268 // Make a trait reference `$0 : Trait<$1...$n>`
269 // consisting entirely of type variables. Later on in
270 // the process we will unify the transformed-self-type
271 // of the method with the actual type in order to
272 // unify some of these variables.
273 let substs = self.infcx().fresh_substs_for_trait(self.span,
274 &trait_def.generics,
275 self.infcx().next_ty_var());
276
277 let trait_ref =
278 ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone()));
279 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
280 method_num: method_num,
281 impl_def_id: None });
282 (substs, origin)
283 }
284
285 probe::WhereClausePick(ref poly_trait_ref, method_num) => {
286 // Where clauses can have bound regions in them. We need to instantiate
287 // those to convert from a poly-trait-ref to a trait-ref.
288 let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
289 let substs = trait_ref.substs.clone();
290 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
291 method_num: method_num,
292 impl_def_id: None });
293 (substs, origin)
294 }
295 }
296 }
297
298 fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
299 F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TyTrait<'tcx>) -> R,
300 {
301 // If we specified that this is an object method, then the
302 // self-type ought to be something that can be dereferenced to
303 // yield an object-type (e.g., `&Object` or `Box<Object>`
304 // etc).
305
306 let (_, _, result) = check::autoderef(self.fcx,
307 self.span,
308 self_ty,
309 None,
310 UnresolvedTypeAction::Error,
311 NoPreference,
312 |ty, _| {
313 match ty.sty {
314 ty::ty_trait(ref data) => Some(closure(self, ty, &**data)),
315 _ => None,
316 }
317 });
318
319 match result {
320 Some(r) => r,
321 None => {
322 self.tcx().sess.span_bug(
323 self.span,
324 &format!("self-type `{}` for ObjectPick never dereferenced to an object",
325 self_ty.repr(self.tcx())))
326 }
327 }
328 }
329
330 fn instantiate_method_substs(&mut self,
331 pick: &probe::Pick<'tcx>,
332 supplied_method_types: Vec<Ty<'tcx>>)
333 -> (Vec<Ty<'tcx>>, Vec<ty::Region>)
334 {
335 // Determine the values for the generic parameters of the method.
336 // If they were not explicitly supplied, just construct fresh
337 // variables.
338 let num_supplied_types = supplied_method_types.len();
339 let num_method_types = pick.item.as_opt_method().unwrap()
340 .generics.types.len(subst::FnSpace);
341 let method_types = {
342 if num_supplied_types == 0 {
343 self.fcx.infcx().next_ty_vars(num_method_types)
344 } else if num_method_types == 0 {
345 span_err!(self.tcx().sess, self.span, E0035,
346 "does not take type parameters");
347 self.fcx.infcx().next_ty_vars(num_method_types)
348 } else if num_supplied_types != num_method_types {
349 span_err!(self.tcx().sess, self.span, E0036,
350 "incorrect number of type parameters given for this method");
351 repeat(self.tcx().types.err).take(num_method_types).collect()
352 } else {
353 supplied_method_types
354 }
355 };
356
357 // Create subst for early-bound lifetime parameters, combining
358 // parameters from the type and those from the method.
359 //
360 // FIXME -- permit users to manually specify lifetimes
361 let method_regions =
362 self.fcx.infcx().region_vars_for_defs(
363 self.span,
364 pick.item.as_opt_method().unwrap()
365 .generics.regions.get_slice(subst::FnSpace));
366
367 (method_types, method_regions)
368 }
369
370 fn unify_receivers(&mut self,
371 self_ty: Ty<'tcx>,
372 method_self_ty: Ty<'tcx>)
373 {
374 match self.fcx.mk_subty(false, infer::Misc(self.span), self_ty, method_self_ty) {
375 Ok(_) => {}
376 Err(_) => {
377 self.tcx().sess.span_bug(
378 self.span,
379 &format!(
380 "{} was a subtype of {} but now is not?",
381 self_ty.repr(self.tcx()),
382 method_self_ty.repr(self.tcx())));
383 }
384 }
385 }
386
387 ///////////////////////////////////////////////////////////////////////////
388 //
389
390 fn instantiate_method_sig(&mut self,
391 pick: &probe::Pick<'tcx>,
392 all_substs: subst::Substs<'tcx>)
393 -> InstantiatedMethodSig<'tcx>
394 {
395 debug!("instantiate_method_sig(pick={}, all_substs={})",
396 pick.repr(self.tcx()),
397 all_substs.repr(self.tcx()));
398
399 // Instantiate the bounds on the method with the
400 // type/early-bound-regions substitutions performed. There can
401 // be no late-bound regions appearing here.
402 let method_predicates = pick.item.as_opt_method().unwrap()
403 .predicates.instantiate(self.tcx(), &all_substs);
404 let method_predicates = self.fcx.normalize_associated_types_in(self.span,
405 &method_predicates);
406
407 debug!("method_predicates after subst = {}",
408 method_predicates.repr(self.tcx()));
409
410 // Instantiate late-bound regions and substitute the trait
411 // parameters into the method type to get the actual method type.
412 //
413 // NB: Instantiate late-bound regions first so that
414 // `instantiate_type_scheme` can normalize associated types that
415 // may reference those regions.
416 let method_sig = self.replace_late_bound_regions_with_fresh_var(
417 &pick.item.as_opt_method().unwrap().fty.sig);
418 debug!("late-bound lifetimes from method instantiated, method_sig={}",
419 method_sig.repr(self.tcx()));
420
421 let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig);
422 debug!("type scheme substituted, method_sig={}",
423 method_sig.repr(self.tcx()));
424
425 InstantiatedMethodSig {
426 method_sig: method_sig,
427 all_substs: all_substs,
428 method_predicates: method_predicates,
429 }
430 }
431
432 fn add_obligations(&mut self,
433 pick: &probe::Pick<'tcx>,
434 all_substs: &subst::Substs<'tcx>,
435 method_predicates: &ty::InstantiatedPredicates<'tcx>) {
436 debug!("add_obligations: pick={} all_substs={} method_predicates={}",
437 pick.repr(self.tcx()),
438 all_substs.repr(self.tcx()),
439 method_predicates.repr(self.tcx()));
440
441 self.fcx.add_obligations_for_parameters(
442 traits::ObligationCause::misc(self.span, self.fcx.body_id),
443 method_predicates);
444
445 self.fcx.add_default_region_param_bounds(
446 all_substs,
447 self.call_expr);
448 }
449
450 ///////////////////////////////////////////////////////////////////////////
451 // RECONCILIATION
452
453 /// When we select a method with an `&mut self` receiver, we have to go convert any
454 /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut`
455 /// respectively.
456 fn fixup_derefs_on_method_receiver_if_necessary(&self,
457 method_callee: &MethodCallee) {
458 let sig = match method_callee.ty.sty {
459 ty::ty_bare_fn(_, ref f) => f.sig.clone(),
460 _ => return,
461 };
462
463 match sig.0.inputs[0].sty {
464 ty::ty_rptr(_, ty::mt {
465 ty: _,
466 mutbl: ast::MutMutable,
467 }) => {}
468 _ => return,
469 }
470
471 // Gather up expressions we want to munge.
472 let mut exprs = Vec::new();
473 exprs.push(self.self_expr);
474 loop {
475 let last = exprs[exprs.len() - 1];
476 match last.node {
477 ast::ExprParen(ref expr) |
478 ast::ExprField(ref expr, _) |
479 ast::ExprTupField(ref expr, _) |
480 ast::ExprIndex(ref expr, _) |
481 ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr),
482 _ => break,
483 }
484 }
485
486 debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={}",
487 exprs.repr(self.tcx()));
488
489 // Fix up autoderefs and derefs.
490 for (i, &expr) in exprs.iter().rev().enumerate() {
491 // Count autoderefs.
492 let autoderef_count = match self.fcx
493 .inh
494 .adjustments
495 .borrow()
496 .get(&expr.id) {
497 Some(&ty::AdjustDerefRef(ref adj)) => adj.autoderefs,
498 Some(_) | None => 0,
499 };
500
501 debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={} autoderef_count={}",
502 i, expr.repr(self.tcx()), autoderef_count);
503
504 if autoderef_count > 0 {
505 check::autoderef(self.fcx,
506 expr.span,
507 self.fcx.expr_ty(expr),
508 Some(expr),
509 UnresolvedTypeAction::Error,
510 PreferMutLvalue,
511 |_, autoderefs| {
512 if autoderefs == autoderef_count + 1 {
513 Some(())
514 } else {
515 None
516 }
517 });
518 }
519
520 // Don't retry the first one or we might infinite loop!
521 if i != 0 {
522 match expr.node {
523 ast::ExprIndex(ref base_expr, ref index_expr) => {
524 // If this is an overloaded index, the
525 // adjustment will include an extra layer of
526 // autoref because the method is an &self/&mut
527 // self method. We have to peel it off to get
528 // the raw adjustment that `try_index_step`
529 // expects. This is annoying and horrible. We
530 // ought to recode this routine so it doesn't
531 // (ab)use the normal type checking paths.
532 let adj = self.fcx.inh.adjustments.borrow().get(&base_expr.id).cloned();
533 let (autoderefs, unsize) = match adj {
534 Some(ty::AdjustDerefRef(adr)) => match adr.autoref {
535 None => {
536 assert!(adr.unsize.is_none());
537 (adr.autoderefs, None)
538 }
539 Some(ty::AutoPtr(_, _)) => {
540 (adr.autoderefs, adr.unsize.map(|target| {
541 ty::deref(target, false)
542 .expect("fixup: AutoPtr is not &T").ty
543 }))
544 }
545 Some(_) => {
546 self.tcx().sess.span_bug(
547 base_expr.span,
548 &format!("unexpected adjustment autoref {}",
549 adr.repr(self.tcx())));
550 }
551 },
552 None => (0, None),
553 Some(_) => {
554 self.tcx().sess.span_bug(
555 base_expr.span,
556 "unexpected adjustment type");
557 }
558 };
559
560 let (adjusted_base_ty, unsize) = if let Some(target) = unsize {
561 (target, true)
562 } else {
563 (self.fcx.adjust_expr_ty(base_expr,
564 Some(&ty::AdjustDerefRef(ty::AutoDerefRef {
565 autoderefs: autoderefs,
566 autoref: None,
567 unsize: None
568 }))), false)
569 };
570 let index_expr_ty = self.fcx.expr_ty(&**index_expr);
571
572 let result = check::try_index_step(
573 self.fcx,
574 MethodCall::expr(expr.id),
575 expr,
576 &**base_expr,
577 adjusted_base_ty,
578 autoderefs,
579 unsize,
580 PreferMutLvalue,
581 index_expr_ty);
582
583 if let Some((input_ty, return_ty)) = result {
584 demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
585
586 let expr_ty = self.fcx.expr_ty(&*expr);
587 demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
588 }
589 }
590 ast::ExprUnary(ast::UnDeref, ref base_expr) => {
591 // if this is an overloaded deref, then re-evaluate with
592 // a preference for mut
593 let method_call = MethodCall::expr(expr.id);
594 if self.fcx.inh.method_map.borrow().contains_key(&method_call) {
595 check::try_overloaded_deref(
596 self.fcx,
597 expr.span,
598 Some(method_call),
599 Some(&**base_expr),
600 self.fcx.expr_ty(&**base_expr),
601 PreferMutLvalue);
602 }
603 }
604 _ => {}
605 }
606 }
607 }
608 }
609
610 ///////////////////////////////////////////////////////////////////////////
611 // MISCELLANY
612
613 fn tcx(&self) -> &'a ty::ctxt<'tcx> {
614 self.fcx.tcx()
615 }
616
617 fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
618 self.fcx.infcx()
619 }
620
621 fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) {
622 // Disallow calls to the method `drop` defined in the `Drop` trait.
623 match pick.item.container() {
624 ty::TraitContainer(trait_def_id) => {
625 callee::check_legal_trait_for_method_call(self.fcx.ccx, self.span, trait_def_id)
626 }
627 ty::ImplContainer(..) => {
628 // Since `drop` is a trait method, we expect that any
629 // potential calls to it will wind up in the other
630 // arm. But just to be sure, check that the method id
631 // does not appear in the list of destructors.
632 assert!(!self.tcx().destructors.borrow().contains(&pick.item.def_id()));
633 }
634 }
635 }
636
637 fn upcast(&mut self,
638 source_trait_ref: ty::PolyTraitRef<'tcx>,
639 target_trait_def_id: ast::DefId)
640 -> ty::PolyTraitRef<'tcx>
641 {
642 let upcast_trait_refs = traits::upcast(self.tcx(),
643 source_trait_ref.clone(),
644 target_trait_def_id);
645
646 // must be exactly one trait ref or we'd get an ambig error etc
647 if upcast_trait_refs.len() != 1 {
648 self.tcx().sess.span_bug(
649 self.span,
650 &format!("cannot uniquely upcast `{}` to `{}`: `{}`",
651 source_trait_ref.repr(self.tcx()),
652 target_trait_def_id.repr(self.tcx()),
653 upcast_trait_refs.repr(self.tcx())));
654 }
655
656 upcast_trait_refs.into_iter().next().unwrap()
657 }
658
659 fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
660 where T : TypeFoldable<'tcx> + Repr<'tcx>
661 {
662 self.infcx().replace_late_bound_regions_with_fresh_var(
663 self.span, infer::FnCall, value).0
664 }
665 }