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