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