]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/method/confirm.rs
core: Fix size_hint for signed integer Range<T> iterators
[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 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                       pick: &probe::Pick<'tcx>)
137                       -> Ty<'tcx>
138     {
139         let (autoref, unsize) = if let Some(mutbl) = pick.autoref {
140             let region = self.infcx().next_region_var(infer::Autoref(self.span));
141             let autoref = ty::AutoPtr(self.tcx().mk_region(region), mutbl);
142             (Some(autoref), pick.unsize.map(|target| {
143                 ty::adjust_ty_for_autoref(self.tcx(), target, Some(autoref))
144             }))
145         } else {
146             // No unsizing should be performed without autoref (at
147             // least during method dispach). This is because we
148             // currently only unsize `[T;N]` to `[T]`, and naturally
149             // that must occur being a reference.
150             assert!(pick.unsize.is_none());
151             (None, None)
152         };
153
154         // Commit the autoderefs by calling `autoderef again, but this
155         // time writing the results into the various tables.
156         let (autoderefd_ty, n, result) = check::autoderef(self.fcx,
157                                                           self.span,
158                                                           unadjusted_self_ty,
159                                                           Some(self.self_expr),
160                                                           UnresolvedTypeAction::Error,
161                                                           NoPreference,
162                                                           |_, n| {
163             if n == pick.autoderefs {
164                 Some(())
165             } else {
166                 None
167             }
168         });
169         assert_eq!(n, pick.autoderefs);
170         assert_eq!(result, Some(()));
171
172         // Write out the final adjustment.
173         self.fcx.write_adjustment(self.self_expr.id,
174                                   ty::AdjustDerefRef(ty::AutoDerefRef {
175             autoderefs: pick.autoderefs,
176             autoref: autoref,
177             unsize: unsize
178         }));
179
180         if let Some(target) = unsize {
181             target
182         } else {
183             ty::adjust_ty_for_autoref(self.tcx(), autoderefd_ty, autoref)
184         }
185     }
186
187     ///////////////////////////////////////////////////////////////////////////
188     //
189
190     /// Returns a set of substitutions for the method *receiver* where all type and region
191     /// parameters are instantiated with fresh variables. This substitution does not include any
192     /// parameters declared on the method itself.
193     ///
194     /// Note that this substitution may include late-bound regions from the impl level. If so,
195     /// these are instantiated later in the `instantiate_method_sig` routine.
196     fn fresh_receiver_substs(&mut self,
197                              self_ty: Ty<'tcx>,
198                              pick: &probe::Pick<'tcx>)
199                              -> (subst::Substs<'tcx>, MethodOrigin<'tcx>)
200     {
201         match pick.kind {
202             probe::InherentImplPick(impl_def_id) => {
203                 assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(),
204                         "impl {:?} is not an inherent impl", impl_def_id);
205                 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
206
207                 (impl_polytype.substs, MethodStatic(pick.method_ty.def_id))
208             }
209
210             probe::ObjectPick(trait_def_id, method_num, vtable_index) => {
211                 self.extract_trait_ref(self_ty, |this, object_ty, data| {
212                     // The object data has no entry for the Self
213                     // Type. For the purposes of this method call, we
214                     // substitute the object type itself. This
215                     // wouldn't be a sound substitution in all cases,
216                     // since each instance of the object type is a
217                     // different existential and hence could match
218                     // distinct types (e.g., if `Self` appeared as an
219                     // argument type), but those cases have already
220                     // been ruled out when we deemed the trait to be
221                     // "object safe".
222                     let original_poly_trait_ref =
223                         data.principal_trait_ref_with_self_ty(this.tcx(), object_ty);
224                     let upcast_poly_trait_ref =
225                         this.upcast(original_poly_trait_ref.clone(), trait_def_id);
226                     let upcast_trait_ref =
227                         this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
228                     debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}",
229                            original_poly_trait_ref.repr(this.tcx()),
230                            upcast_trait_ref.repr(this.tcx()),
231                            trait_def_id.repr(this.tcx()));
232                     let substs = upcast_trait_ref.substs.clone();
233                     let origin = MethodTraitObject(MethodObject {
234                         trait_ref: upcast_trait_ref,
235                         object_trait_id: trait_def_id,
236                         method_num: method_num,
237                         vtable_index: vtable_index,
238                     });
239                     (substs, origin)
240                 })
241             }
242
243             probe::ExtensionImplPick(impl_def_id, method_num) => {
244                 // The method being invoked is the method as defined on the trait,
245                 // so return the substitutions from the trait. Consider:
246                 //
247                 //     impl<A,B,C> Trait<A,B> for Foo<C> { ... }
248                 //
249                 // If we instantiate A, B, and C with $A, $B, and $C
250                 // respectively, then we want to return the type
251                 // parameters from the trait ([$A,$B]), not those from
252                 // the impl ([$A,$B,$C]) not the receiver type ([$C]).
253                 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
254                 let impl_trait_ref =
255                     self.fcx.instantiate_type_scheme(
256                         self.span,
257                         &impl_polytype.substs,
258                         &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
259                 let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
260                                                            method_num: method_num,
261                                                            impl_def_id: Some(impl_def_id) });
262                 (impl_trait_ref.substs.clone(), origin)
263             }
264
265             probe::TraitPick(trait_def_id, method_num) => {
266                 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
267
268                 // Make a trait reference `$0 : Trait<$1...$n>`
269                 // consisting entirely of type variables. Later on in
270                 // the process we will unify the transformed-self-type
271                 // of the method with the actual type in order to
272                 // unify some of these variables.
273                 let substs = self.infcx().fresh_substs_for_trait(self.span,
274                                                                  &trait_def.generics,
275                                                                  self.infcx().next_ty_var());
276
277                 let trait_ref =
278                     Rc::new(ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone())));
279                 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
280                                                            method_num: method_num,
281                                                            impl_def_id: None });
282                 (substs, origin)
283             }
284
285             probe::WhereClausePick(ref poly_trait_ref, method_num) => {
286                 // Where clauses can have bound regions in them. We need to instantiate
287                 // those to convert from a poly-trait-ref to a trait-ref.
288                 let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
289                 let substs = trait_ref.substs.clone();
290                 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
291                                                            method_num: method_num,
292                                                            impl_def_id: None });
293                 (substs, origin)
294             }
295         }
296     }
297
298     fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
299         F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TyTrait<'tcx>) -> R,
300     {
301         // If we specified that this is an object method, then the
302         // self-type ought to be something that can be dereferenced to
303         // yield an object-type (e.g., `&Object` or `Box<Object>`
304         // etc).
305
306         let (_, _, result) = check::autoderef(self.fcx,
307                                               self.span,
308                                               self_ty,
309                                               None,
310                                               UnresolvedTypeAction::Error,
311                                               NoPreference,
312                                               |ty, _| {
313             match ty.sty {
314                 ty::ty_trait(ref data) => Some(closure(self, ty, &**data)),
315                 _ => None,
316             }
317         });
318
319         match result {
320             Some(r) => r,
321             None => {
322                 self.tcx().sess.span_bug(
323                     self.span,
324                     &format!("self-type `{}` for ObjectPick never dereferenced to an object",
325                             self_ty.repr(self.tcx())))
326             }
327         }
328     }
329
330     fn instantiate_method_substs(&mut self,
331                                  pick: &probe::Pick<'tcx>,
332                                  supplied_method_types: Vec<Ty<'tcx>>)
333                                  -> (Vec<Ty<'tcx>>, Vec<ty::Region>)
334     {
335         // Determine the values for the generic parameters of the method.
336         // If they were not explicitly supplied, just construct fresh
337         // variables.
338         let num_supplied_types = supplied_method_types.len();
339         let num_method_types = pick.method_ty.generics.types.len(subst::FnSpace);
340         let method_types = {
341             if num_supplied_types == 0 {
342                 self.fcx.infcx().next_ty_vars(num_method_types)
343             } else if num_method_types == 0 {
344                 span_err!(self.tcx().sess, self.span, E0035,
345                     "does not take type parameters");
346                 self.fcx.infcx().next_ty_vars(num_method_types)
347             } else if num_supplied_types != num_method_types {
348                 span_err!(self.tcx().sess, self.span, E0036,
349                     "incorrect number of type parameters given for this method");
350                 repeat(self.tcx().types.err).take(num_method_types).collect()
351             } else {
352                 supplied_method_types
353             }
354         };
355
356         // Create subst for early-bound lifetime parameters, combining
357         // parameters from the type and those from the method.
358         //
359         // FIXME -- permit users to manually specify lifetimes
360         let method_regions =
361             self.fcx.infcx().region_vars_for_defs(
362                 self.span,
363                 pick.method_ty.generics.regions.get_slice(subst::FnSpace));
364
365         (method_types, method_regions)
366     }
367
368     fn unify_receivers(&mut self,
369                        self_ty: Ty<'tcx>,
370                        method_self_ty: Ty<'tcx>)
371     {
372         match self.fcx.mk_subty(false, infer::Misc(self.span), self_ty, method_self_ty) {
373             Ok(_) => {}
374             Err(_) => {
375                 self.tcx().sess.span_bug(
376                     self.span,
377                     &format!(
378                         "{} was a subtype of {} but now is not?",
379                         self_ty.repr(self.tcx()),
380                         method_self_ty.repr(self.tcx())));
381             }
382         }
383     }
384
385     ///////////////////////////////////////////////////////////////////////////
386     //
387
388     fn instantiate_method_sig(&mut self,
389                               pick: &probe::Pick<'tcx>,
390                               all_substs: subst::Substs<'tcx>)
391                               -> InstantiatedMethodSig<'tcx>
392     {
393         debug!("instantiate_method_sig(pick={}, all_substs={})",
394                pick.repr(self.tcx()),
395                all_substs.repr(self.tcx()));
396
397         // Instantiate the bounds on the method with the
398         // type/early-bound-regions substitutions performed. There can
399         // be no late-bound regions appearing here.
400         let method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
401         let method_predicates = self.fcx.normalize_associated_types_in(self.span,
402                                                                        &method_predicates);
403
404         debug!("method_predicates after subst = {}",
405                method_predicates.repr(self.tcx()));
406
407         // Instantiate late-bound regions and substitute the trait
408         // parameters into the method type to get the actual method type.
409         //
410         // NB: Instantiate late-bound regions first so that
411         // `instantiate_type_scheme` can normalize associated types that
412         // may reference those regions.
413         let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.method_ty.fty.sig);
414         debug!("late-bound lifetimes from method instantiated, method_sig={}",
415                method_sig.repr(self.tcx()));
416
417         let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig);
418         debug!("type scheme substituted, method_sig={}",
419                method_sig.repr(self.tcx()));
420
421         InstantiatedMethodSig {
422             method_sig: method_sig,
423             all_substs: all_substs,
424             method_predicates: method_predicates,
425         }
426     }
427
428     fn add_obligations(&mut self,
429                        pick: &probe::Pick<'tcx>,
430                        all_substs: &subst::Substs<'tcx>,
431                        method_predicates: &ty::InstantiatedPredicates<'tcx>) {
432         debug!("add_obligations: pick={} all_substs={} method_predicates={}",
433                pick.repr(self.tcx()),
434                all_substs.repr(self.tcx()),
435                method_predicates.repr(self.tcx()));
436
437         self.fcx.add_obligations_for_parameters(
438             traits::ObligationCause::misc(self.span, self.fcx.body_id),
439             method_predicates);
440
441         self.fcx.add_default_region_param_bounds(
442             all_substs,
443             self.call_expr);
444     }
445
446     ///////////////////////////////////////////////////////////////////////////
447     // RECONCILIATION
448
449     /// When we select a method with an `&mut self` receiver, we have to go convert any
450     /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut`
451     /// respectively.
452     fn fixup_derefs_on_method_receiver_if_necessary(&self,
453                                                     method_callee: &MethodCallee) {
454         let sig = match method_callee.ty.sty {
455             ty::ty_bare_fn(_, ref f) => f.sig.clone(),
456             _ => return,
457         };
458
459         match sig.0.inputs[0].sty {
460             ty::ty_rptr(_, ty::mt {
461                 ty: _,
462                 mutbl: ast::MutMutable,
463             }) => {}
464             _ => return,
465         }
466
467         // Gather up expressions we want to munge.
468         let mut exprs = Vec::new();
469         exprs.push(self.self_expr);
470         loop {
471             let last = exprs[exprs.len() - 1];
472             match last.node {
473                 ast::ExprParen(ref expr) |
474                 ast::ExprField(ref expr, _) |
475                 ast::ExprTupField(ref expr, _) |
476                 ast::ExprIndex(ref expr, _) |
477                 ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr),
478                 _ => break,
479             }
480         }
481
482         debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={}",
483                exprs.repr(self.tcx()));
484
485         // Fix up autoderefs and derefs.
486         for (i, &expr) in exprs.iter().rev().enumerate() {
487             // Count autoderefs.
488             let autoderef_count = match self.fcx
489                                             .inh
490                                             .adjustments
491                                             .borrow()
492                                             .get(&expr.id) {
493                 Some(&ty::AdjustDerefRef(ref adj)) => adj.autoderefs,
494                 Some(_) | None => 0,
495             };
496
497             debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={} autoderef_count={}",
498                    i, expr.repr(self.tcx()), autoderef_count);
499
500             if autoderef_count > 0 {
501                 check::autoderef(self.fcx,
502                                  expr.span,
503                                  self.fcx.expr_ty(expr),
504                                  Some(expr),
505                                  UnresolvedTypeAction::Error,
506                                  PreferMutLvalue,
507                                  |_, autoderefs| {
508                                      if autoderefs == autoderef_count + 1 {
509                                          Some(())
510                                      } else {
511                                          None
512                                      }
513                                  });
514             }
515
516             // Don't retry the first one or we might infinite loop!
517             if i != 0 {
518                 match expr.node {
519                     ast::ExprIndex(ref base_expr, ref index_expr) => {
520                         // If this is an overloaded index, the
521                         // adjustment will include an extra layer of
522                         // autoref because the method is an &self/&mut
523                         // self method. We have to peel it off to get
524                         // the raw adjustment that `try_index_step`
525                         // expects. This is annoying and horrible. We
526                         // ought to recode this routine so it doesn't
527                         // (ab)use the normal type checking paths.
528                         let adj = self.fcx.inh.adjustments.borrow().get(&base_expr.id).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                                         ty::deref(target, 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.repr(self.tcx())));
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                             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 = MethodCall::expr(expr.id);
590                         if self.fcx.inh.method_map.borrow().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.method_ty.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.method_ty.def_id));
629             }
630         }
631     }
632
633     fn upcast(&mut self,
634               source_trait_ref: ty::PolyTraitRef<'tcx>,
635               target_trait_def_id: ast::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.repr(self.tcx()),
648                          target_trait_def_id.repr(self.tcx()),
649                          upcast_trait_refs.repr(self.tcx())));
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> + Repr<'tcx>
657     {
658         self.infcx().replace_late_bound_regions_with_fresh_var(
659             self.span, infer::FnCall, value).0
660     }
661 }