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