]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/method/confirm.rs
Merge pull request #20674 from jbcrail/fix-misspelled-comments
[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 middle::mem_categorization::Typer;
15 use middle::subst::{self};
16 use middle::traits;
17 use middle::ty::{self, Ty};
18 use middle::ty::{MethodCall, MethodCallee, MethodObject, MethodOrigin,
19                  MethodParam, MethodStatic, MethodTraitObject, MethodTypeParam};
20 use middle::ty_fold::TypeFoldable;
21 use middle::infer;
22 use middle::infer::InferCtxt;
23 use syntax::ast;
24 use syntax::codemap::Span;
25 use std::rc::Rc;
26 use std::mem;
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: &'a ast::Expr,
34     call_expr: &'a 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_bounds: ty::GenericBounds<'tcx>,
49 }
50
51 pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
52                          span: Span,
53                          self_expr: &ast::Expr,
54                          call_expr: &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: &'a ast::Expr,
73            call_expr: &'a 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.adjustment);
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_bounds
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_bounds);
110
111         // Create the final `MethodCallee`.
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: pick.method_ty.fty.unsafety,
115             abi: pick.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                       adjustment: &probe::PickAdjustment)
137                       -> Ty<'tcx>
138     {
139         // Construct the actual adjustment and write it into the table
140         let auto_deref_ref = self.create_ty_adjustment(adjustment);
141
142         // Commit the autoderefs by calling `autoderef again, but this
143         // time writing the results into the various tables.
144         let (autoderefd_ty, n, result) =
145             check::autoderef(
146                 self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr.id), NoPreference,
147                 |_, n| if n == auto_deref_ref.autoderefs { Some(()) } else { None });
148         assert_eq!(n, auto_deref_ref.autoderefs);
149         assert_eq!(result, Some(()));
150
151         let final_ty =
152             ty::adjust_ty_for_autoref(self.tcx(), self.span, autoderefd_ty,
153                                       auto_deref_ref.autoref.as_ref());
154
155         // Write out the final adjustment.
156         self.fcx.write_adjustment(self.self_expr.id, self.span, ty::AdjustDerefRef(auto_deref_ref));
157
158         final_ty
159     }
160
161     fn create_ty_adjustment(&mut self,
162                             adjustment: &probe::PickAdjustment)
163                             -> ty::AutoDerefRef<'tcx>
164     {
165         match *adjustment {
166             probe::AutoDeref(num) => {
167                 ty::AutoDerefRef {
168                     autoderefs: num,
169                     autoref: None
170                 }
171             }
172             probe::AutoUnsizeLength(autoderefs, len) => {
173                 ty::AutoDerefRef {
174                     autoderefs: autoderefs,
175                     autoref: Some(ty::AutoUnsize(ty::UnsizeLength(len)))
176                 }
177             }
178             probe::AutoRef(mutability, ref sub_adjustment) => {
179                 let deref = self.create_ty_adjustment(&**sub_adjustment);
180                 let region = self.infcx().next_region_var(infer::Autoref(self.span));
181                 wrap_autoref(deref, |base| ty::AutoPtr(region, mutability, base))
182             }
183         }
184     }
185
186     ///////////////////////////////////////////////////////////////////////////
187     //
188
189     /// Returns a set of substitutions for the method *receiver* where all type and region
190     /// parameters are instantiated with fresh variables. This substitution does not include any
191     /// parameters declared on the method itself.
192     ///
193     /// Note that this substitution may include late-bound regions from the impl level. If so,
194     /// these are instantiated later in the `instantiate_method_sig` routine.
195     fn fresh_receiver_substs(&mut self,
196                              self_ty: Ty<'tcx>,
197                              pick: &probe::Pick<'tcx>)
198                              -> (subst::Substs<'tcx>, MethodOrigin<'tcx>)
199     {
200         match pick.kind {
201             probe::InherentImplPick(impl_def_id) => {
202                 assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(),
203                         "impl {:?} is not an inherent impl", impl_def_id);
204                 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
205
206                 (impl_polytype.substs, MethodStatic(pick.method_ty.def_id))
207             }
208
209             probe::ObjectPick(trait_def_id, method_num, real_index) => {
210                 self.extract_trait_ref(self_ty, |this, object_ty, data| {
211                     // The object data has no entry for the Self
212                     // Type. For the purposes of this method call, we
213                     // substitute the object type itself. This
214                     // wouldn't be a sound substitution in all cases,
215                     // since each instance of the object type is a
216                     // different existential and hence could match
217                     // distinct types (e.g., if `Self` appeared as an
218                     // argument type), but those cases have already
219                     // been ruled out when we deemed the trait to be
220                     // "object safe".
221                     let original_poly_trait_ref =
222                         data.principal_trait_ref_with_self_ty(this.tcx(), object_ty);
223                     let upcast_poly_trait_ref =
224                         this.upcast(original_poly_trait_ref.clone(), trait_def_id);
225                     let upcast_trait_ref =
226                         this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
227                     debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}",
228                            original_poly_trait_ref.repr(this.tcx()),
229                            upcast_trait_ref.repr(this.tcx()),
230                            trait_def_id.repr(this.tcx()));
231                     let substs = upcast_trait_ref.substs.clone();
232                     let origin = MethodTraitObject(MethodObject {
233                         trait_ref: upcast_trait_ref,
234                         object_trait_id: trait_def_id,
235                         method_num: method_num,
236                         real_index: real_index,
237                     });
238                     (substs, origin)
239                 })
240             }
241
242             probe::ExtensionImplPick(impl_def_id, method_num) => {
243                 // The method being invoked is the method as defined on the trait,
244                 // so return the substitutions from the trait. Consider:
245                 //
246                 //     impl<A,B,C> Trait<A,B> for Foo<C> { ... }
247                 //
248                 // If we instantiate A, B, and C with $A, $B, and $C
249                 // respectively, then we want to return the type
250                 // parameters from the trait ([$A,$B]), not those from
251                 // the impl ([$A,$B,$C]) not the receiver type ([$C]).
252                 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
253                 let impl_trait_ref =
254                     self.fcx.instantiate_type_scheme(
255                         self.span,
256                         &impl_polytype.substs,
257                         &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
258                 let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
259                                                            method_num: method_num });
260                 (impl_trait_ref.substs.clone(), origin)
261             }
262
263             probe::TraitPick(trait_def_id, method_num) => {
264                 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
265
266                 // Make a trait reference `$0 : Trait<$1...$n>`
267                 // consisting entirely of type variables. Later on in
268                 // the process we will unify the transformed-self-type
269                 // of the method with the actual type in order to
270                 // unify some of these variables.
271                 let substs = self.infcx().fresh_substs_for_trait(self.span,
272                                                                  &trait_def.generics,
273                                                                  self.infcx().next_ty_var());
274
275                 let trait_ref =
276                     Rc::new(ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone())));
277                 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
278                                                            method_num: method_num });
279                 (substs, origin)
280             }
281
282             probe::WhereClausePick(ref poly_trait_ref, method_num) => {
283                 // Where clauses can have bound regions in them. We need to instantiate
284                 // those to convert from a poly-trait-ref to a trait-ref.
285                 let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
286                 let substs = trait_ref.substs.clone();
287                 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
288                                                            method_num: method_num });
289                 (substs, origin)
290             }
291         }
292     }
293
294     fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
295         F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TyTrait<'tcx>) -> R,
296     {
297         // If we specified that this is an object method, then the
298         // self-type ought to be something that can be dereferenced to
299         // yield an object-type (e.g., `&Object` or `Box<Object>`
300         // etc).
301
302         let (_, _, result) =
303             check::autoderef(
304                 self.fcx, self.span, self_ty, None, NoPreference,
305                 |ty, _| {
306                     match ty.sty {
307                         ty::ty_trait(ref data) => Some(closure(self, ty, &**data)),
308                         _ => None,
309                     }
310                 });
311
312         match result {
313             Some(r) => r,
314             None => {
315                 self.tcx().sess.span_bug(
316                     self.span,
317                     format!("self-type `{}` for ObjectPick never dereferenced to an object",
318                             self_ty.repr(self.tcx())).index(&FullRange))
319             }
320         }
321     }
322
323     fn instantiate_method_substs(&mut self,
324                                  pick: &probe::Pick<'tcx>,
325                                  supplied_method_types: Vec<Ty<'tcx>>)
326                                  -> (Vec<Ty<'tcx>>, Vec<ty::Region>)
327     {
328         // Determine the values for the generic parameters of the method.
329         // If they were not explicitly supplied, just construct fresh
330         // variables.
331         let num_supplied_types = supplied_method_types.len();
332         let num_method_types = pick.method_ty.generics.types.len(subst::FnSpace);
333         let method_types = {
334             if num_supplied_types == 0u {
335                 self.fcx.infcx().next_ty_vars(num_method_types)
336             } else if num_method_types == 0u {
337                 span_err!(self.tcx().sess, self.span, E0035,
338                     "does not take type parameters");
339                 self.fcx.infcx().next_ty_vars(num_method_types)
340             } else if num_supplied_types != num_method_types {
341                 span_err!(self.tcx().sess, self.span, E0036,
342                     "incorrect number of type parameters given for this method");
343                 repeat(self.tcx().types.err).take(num_method_types).collect()
344             } else {
345                 supplied_method_types
346             }
347         };
348
349         // Create subst for early-bound lifetime parameters, combining
350         // parameters from the type and those from the method.
351         //
352         // FIXME -- permit users to manually specify lifetimes
353         let method_regions =
354             self.fcx.infcx().region_vars_for_defs(
355                 self.span,
356                 pick.method_ty.generics.regions.get_slice(subst::FnSpace));
357
358         (method_types, method_regions)
359     }
360
361     fn unify_receivers(&mut self,
362                        self_ty: Ty<'tcx>,
363                        method_self_ty: Ty<'tcx>)
364     {
365         match self.fcx.mk_subty(false, infer::Misc(self.span), self_ty, method_self_ty) {
366             Ok(_) => {}
367             Err(_) => {
368                 self.tcx().sess.span_bug(
369                     self.span,
370                     format!(
371                         "{} was a subtype of {} but now is not?",
372                         self_ty.repr(self.tcx()),
373                         method_self_ty.repr(self.tcx())).index(&FullRange));
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.repr(self.tcx()),
388                all_substs.repr(self.tcx()));
389
390         // Instantiate the bounds on the method with the
391         // type/early-bound-regions substitutions performed.  The only
392         // late-bound-regions that can appear in bounds are from the
393         // impl, and those were already instantiated above.
394         //
395         // FIXME(DST). Super hack. For a method on a trait object
396         // `Trait`, the generic signature requires that
397         // `Self:Trait`. Since, for an object, we bind `Self` to the
398         // type `Trait`, this leads to an obligation
399         // `Trait:Trait`. Until such time we DST is fully implemented,
400         // that obligation is not necessarily satisfied. (In the
401         // future, it would be.) But we know that the true `Self` DOES implement
402         // the trait. So we just delete this requirement. Hack hack hack.
403         let mut method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &all_substs);
404         match pick.kind {
405             probe::ObjectPick(..) => {
406                 assert_eq!(method_bounds.predicates.get_slice(subst::SelfSpace).len(), 1);
407                 method_bounds.predicates.pop(subst::SelfSpace);
408             }
409             _ => { }
410         }
411         let method_bounds = self.fcx.normalize_associated_types_in(self.span, &method_bounds);
412
413         debug!("method_bounds after subst = {}",
414                method_bounds.repr(self.tcx()));
415
416         // Instantiate late-bound regions and substitute the trait
417         // parameters into the method type to get the actual method type.
418         //
419         // NB: Instantiate late-bound regions first so that
420         // `instantiate_type_scheme` can normalize associated types that
421         // may reference those regions.
422         let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.method_ty.fty.sig);
423         debug!("late-bound lifetimes from method instantiated, method_sig={}",
424                method_sig.repr(self.tcx()));
425
426         let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig);
427         debug!("type scheme substituted, method_sig={}",
428                method_sig.repr(self.tcx()));
429
430         InstantiatedMethodSig {
431             method_sig: method_sig,
432             all_substs: all_substs,
433             method_bounds: method_bounds,
434         }
435     }
436
437     fn add_obligations(&mut self,
438                        pick: &probe::Pick<'tcx>,
439                        all_substs: &subst::Substs<'tcx>,
440                        method_bounds: &ty::GenericBounds<'tcx>) {
441         debug!("add_obligations: pick={} all_substs={} method_bounds={}",
442                pick.repr(self.tcx()),
443                all_substs.repr(self.tcx()),
444                method_bounds.repr(self.tcx()));
445
446         self.fcx.add_obligations_for_parameters(
447             traits::ObligationCause::misc(self.span, self.fcx.body_id),
448             method_bounds);
449
450         self.fcx.add_default_region_param_bounds(
451             all_substs,
452             self.call_expr);
453     }
454
455     ///////////////////////////////////////////////////////////////////////////
456     // RECONCILIATION
457
458     /// When we select a method with an `&mut self` receiver, we have to go convert any
459     /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut`
460     /// respectively.
461     fn fixup_derefs_on_method_receiver_if_necessary(&self,
462                                                     method_callee: &MethodCallee) {
463         let sig = match method_callee.ty.sty {
464             ty::ty_bare_fn(_, ref f) => f.sig.clone(),
465             _ => return,
466         };
467
468         match sig.0.inputs[0].sty {
469             ty::ty_rptr(_, ty::mt {
470                 ty: _,
471                 mutbl: ast::MutMutable,
472             }) => {}
473             _ => return,
474         }
475
476         // Gather up expressions we want to munge.
477         let mut exprs = Vec::new();
478         exprs.push(self.self_expr);
479         loop {
480             let last = exprs[exprs.len() - 1];
481             match last.node {
482                 ast::ExprParen(ref expr) |
483                 ast::ExprField(ref expr, _) |
484                 ast::ExprTupField(ref expr, _) |
485                 ast::ExprIndex(ref expr, _) |
486                 ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr),
487                 _ => break,
488             }
489         }
490
491         debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={}",
492                exprs.repr(self.tcx()));
493
494         // Fix up autoderefs and derefs.
495         for (i, expr) in exprs.iter().rev().enumerate() {
496             // Count autoderefs.
497             let autoderef_count = match self.fcx
498                                             .inh
499                                             .adjustments
500                                             .borrow()
501                                             .get(&expr.id) {
502                 Some(&ty::AdjustDerefRef(ty::AutoDerefRef {
503                     autoderefs: autoderef_count,
504                     autoref: _
505                 })) => autoderef_count,
506                 Some(_) | None => 0,
507             };
508
509             debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={} autoderef_count={}",
510                    i, expr.repr(self.tcx()), autoderef_count);
511
512             if autoderef_count > 0 {
513                 check::autoderef(self.fcx,
514                                  expr.span,
515                                  self.fcx.expr_ty(*expr),
516                                  Some(expr.id),
517                                  PreferMutLvalue,
518                                  |_, autoderefs| {
519                                      if autoderefs == autoderef_count + 1 {
520                                          Some(())
521                                      } else {
522                                          None
523                                      }
524                                  });
525             }
526
527             // Don't retry the first one or we might infinite loop!
528             if i != 0 {
529                 match expr.node {
530                     ast::ExprIndex(ref base_expr, ref index_expr) => {
531                         let mut base_adjustment =
532                             match self.fcx.inh.adjustments.borrow().get(&base_expr.id) {
533                                 Some(&ty::AdjustDerefRef(ref adr)) => (*adr).clone(),
534                                 None => ty::AutoDerefRef { autoderefs: 0, autoref: None },
535                                 Some(_) => {
536                                     self.tcx().sess.span_bug(
537                                         base_expr.span,
538                                         "unexpected adjustment type");
539                                 }
540                             };
541
542                         // If this is an overloaded index, the
543                         // adjustment will include an extra layer of
544                         // autoref because the method is an &self/&mut
545                         // self method. We have to peel it off to get
546                         // the raw adjustment that `try_index_step`
547                         // expects. This is annoying and horrible. We
548                         // ought to recode this routine so it doesn't
549                         // (ab)use the normal type checking paths.
550                         base_adjustment.autoref = match base_adjustment.autoref {
551                             None => { None }
552                             Some(ty::AutoPtr(_, _, None)) => { None }
553                             Some(ty::AutoPtr(_, _, Some(box r))) => { Some(r) }
554                             Some(_) => {
555                                 self.tcx().sess.span_bug(
556                                     base_expr.span,
557                                     "unexpected adjustment autoref");
558                             }
559                         };
560
561                         let adjusted_base_ty =
562                             self.fcx.adjust_expr_ty(
563                                 &**base_expr,
564                                 Some(&ty::AdjustDerefRef(base_adjustment.clone())));
565                         let index_expr_ty = self.fcx.expr_ty(&**index_expr);
566
567                         let result = check::try_index_step(
568                             self.fcx,
569                             MethodCall::expr(expr.id),
570                             *expr,
571                             &**base_expr,
572                             adjusted_base_ty,
573                             base_adjustment,
574                             PreferMutLvalue,
575                             index_expr_ty);
576
577                         if let Some((input_ty, return_ty)) = result {
578                             demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
579
580                             let expr_ty = self.fcx.expr_ty(&**expr);
581                             demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
582                         }
583                     }
584                     ast::ExprUnary(ast::UnDeref, ref base_expr) => {
585                         // if this is an overloaded deref, then re-evaluate with
586                         // a preference for mut
587                         let method_call = MethodCall::expr(expr.id);
588                         if self.fcx.inh.method_map.borrow().contains_key(&method_call) {
589                             check::try_overloaded_deref(
590                                 self.fcx,
591                                 expr.span,
592                                 Some(method_call),
593                                 Some(&**base_expr),
594                                 self.fcx.expr_ty(&**base_expr),
595                                 PreferMutLvalue);
596                         }
597                     }
598                     _ => {}
599                 }
600             }
601         }
602     }
603
604     ///////////////////////////////////////////////////////////////////////////
605     // MISCELLANY
606
607     fn tcx(&self) -> &'a ty::ctxt<'tcx> {
608         self.fcx.tcx()
609     }
610
611     fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
612         self.fcx.infcx()
613     }
614
615     fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) {
616         // Disallow calls to the method `drop` defined in the `Drop` trait.
617         match pick.method_ty.container {
618             ty::TraitContainer(trait_def_id) => {
619                 callee::check_legal_trait_for_method_call(self.fcx.ccx, self.span, trait_def_id)
620             }
621             ty::ImplContainer(..) => {
622                 // Since `drop` is a trait method, we expect that any
623                 // potential calls to it will wind up in the other
624                 // arm. But just to be sure, check that the method id
625                 // does not appear in the list of destructors.
626                 assert!(!self.tcx().destructors.borrow().contains(&pick.method_ty.def_id));
627             }
628         }
629     }
630
631     fn upcast(&mut self,
632               source_trait_ref: ty::PolyTraitRef<'tcx>,
633               target_trait_def_id: ast::DefId)
634               -> ty::PolyTraitRef<'tcx>
635     {
636         match traits::upcast(self.tcx(), source_trait_ref.clone(), target_trait_def_id) {
637             Some(super_trait_ref) => super_trait_ref,
638             None => {
639                 self.tcx().sess.span_bug(
640                     self.span,
641                     format!("cannot upcast `{}` to `{}`",
642                             source_trait_ref.repr(self.tcx()),
643                             target_trait_def_id.repr(self.tcx())).as_slice());
644             }
645         }
646     }
647
648     fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
649         where T : TypeFoldable<'tcx> + Repr<'tcx>
650     {
651         self.infcx().replace_late_bound_regions_with_fresh_var(
652             self.span, infer::FnCall, value).0
653     }
654 }
655
656 fn wrap_autoref<'tcx, F>(mut deref: ty::AutoDerefRef<'tcx>,
657                          base_fn: F)
658                          -> ty::AutoDerefRef<'tcx> where
659     F: FnOnce(Option<Box<ty::AutoRef<'tcx>>>) -> ty::AutoRef<'tcx>,
660 {
661     let autoref = mem::replace(&mut deref.autoref, None);
662     let autoref = autoref.map(|r| box r);
663     deref.autoref = Some(base_fn(autoref));
664     deref
665 }