]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/check/method/confirm.rs
Merge tag 'upstream/1.5.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;
e9174d1e 15use middle::def_id::DefId;
1a4d82fc
JJ
16use middle::subst::{self};
17use middle::traits;
e9174d1e
SL
18use middle::ty::{self, NoPreference, PreferMutLvalue, Ty};
19use middle::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
20use middle::ty::fold::TypeFoldable;
1a4d82fc
JJ
21use middle::infer;
22use middle::infer::InferCtxt;
1a4d82fc 23use syntax::codemap::Span;
e9174d1e 24use rustc_front::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
JJ
100 } = self.instantiate_method_sig(&pick, all_substs);
101 let method_self_ty = method_sig.inputs[0];
102
103 // Unify the (adjusted) self type with what the method expects.
104 self.unify_receivers(self_ty, method_self_ty);
105
b039eaaf 106 // Create the method type
d9579d0f 107 let method_ty = pick.item.as_opt_method().unwrap();
c1a9b12d 108 let fty = self.tcx().mk_fn(None, self.tcx().mk_bare_fn(ty::BareFnTy {
1a4d82fc 109 sig: ty::Binder(method_sig),
d9579d0f
AL
110 unsafety: method_ty.fty.unsafety,
111 abi: method_ty.fty.abi.clone(),
1a4d82fc 112 }));
b039eaaf
SL
113
114 // Add any trait/regions obligations specified on the method's type parameters.
115 self.add_obligations(fty, &all_substs, &method_predicates);
116
117 // Create the final `MethodCallee`.
c1a9b12d
SL
118 let callee = ty::MethodCallee {
119 def_id: pick.item.def_id(),
1a4d82fc 120 ty: fty,
c1a9b12d 121 substs: self.tcx().mk_substs(all_substs)
1a4d82fc 122 };
1a4d82fc
JJ
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>,
9346a6ac 136 pick: &probe::Pick<'tcx>)
1a4d82fc
JJ
137 -> Ty<'tcx>
138 {
9346a6ac
AL
139 let (autoref, unsize) = if let Some(mutbl) = pick.autoref {
140 let region = self.infcx().next_region_var(infer::Autoref(self.span));
e9174d1e 141 let autoref = AutoPtr(self.tcx().mk_region(region), mutbl);
9346a6ac 142 (Some(autoref), pick.unsize.map(|target| {
c1a9b12d 143 target.adjust_for_autoref(self.tcx(), Some(autoref))
9346a6ac
AL
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 };
1a4d82fc
JJ
153
154 // Commit the autoderefs by calling `autoderef again, but this
155 // time writing the results into the various tables.
85aaf69f
SL
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| {
9346a6ac 163 if n == pick.autoderefs {
85aaf69f
SL
164 Some(())
165 } else {
166 None
167 }
168 });
9346a6ac 169 assert_eq!(n, pick.autoderefs);
1a4d82fc
JJ
170 assert_eq!(result, Some(()));
171
1a4d82fc 172 // Write out the final adjustment.
9346a6ac 173 self.fcx.write_adjustment(self.self_expr.id,
e9174d1e 174 AdjustDerefRef(AutoDerefRef {
9346a6ac
AL
175 autoderefs: pick.autoderefs,
176 autoref: autoref,
177 unsize: unsize
178 }));
1a4d82fc 179
9346a6ac
AL
180 if let Some(target) = unsize {
181 target
182 } else {
c1a9b12d 183 autoderefd_ty.adjust_for_autoref(self.tcx(), autoref)
1a4d82fc
JJ
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>)
c1a9b12d 199 -> subst::Substs<'tcx>
1a4d82fc
JJ
200 {
201 match pick.kind {
c1a9b12d
SL
202 probe::InherentImplPick => {
203 let impl_def_id = pick.item.container().id();
204 assert!(self.tcx().impl_trait_ref(impl_def_id).is_none(),
1a4d82fc 205 "impl {:?} is not an inherent impl", impl_def_id);
c1a9b12d 206 check::impl_self_ty(self.fcx, self.span, impl_def_id).substs
1a4d82fc
JJ
207 }
208
c1a9b12d
SL
209 probe::ObjectPick => {
210 let trait_def_id = pick.item.container().id();
1a4d82fc
JJ
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);
62682a34
SL
228 debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
229 original_poly_trait_ref,
230 upcast_trait_ref,
231 trait_def_id);
c1a9b12d 232 upcast_trait_ref.substs.clone()
1a4d82fc
JJ
233 })
234 }
235
c1a9b12d 236 probe::ExtensionImplPick(impl_def_id) => {
1a4d82fc
JJ
237 // The method being invoked is the method as defined on the trait,
238 // so return the substitutions from the trait. Consider:
239 //
240 // impl<A,B,C> Trait<A,B> for Foo<C> { ... }
241 //
242 // If we instantiate A, B, and C with $A, $B, and $C
243 // respectively, then we want to return the type
244 // parameters from the trait ([$A,$B]), not those from
245 // the impl ([$A,$B,$C]) not the receiver type ([$C]).
246 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
247 let impl_trait_ref =
248 self.fcx.instantiate_type_scheme(
249 self.span,
250 &impl_polytype.substs,
c1a9b12d
SL
251 &self.tcx().impl_trait_ref(impl_def_id).unwrap());
252 impl_trait_ref.substs.clone()
1a4d82fc
JJ
253 }
254
c1a9b12d
SL
255 probe::TraitPick => {
256 let trait_def_id = pick.item.container().id();
257 let trait_def = self.tcx().lookup_trait_def(trait_def_id);
1a4d82fc
JJ
258
259 // Make a trait reference `$0 : Trait<$1...$n>`
260 // consisting entirely of type variables. Later on in
261 // the process we will unify the transformed-self-type
262 // of the method with the actual type in order to
263 // unify some of these variables.
c1a9b12d
SL
264 self.infcx().fresh_substs_for_trait(self.span,
265 &trait_def.generics,
266 self.infcx().next_ty_var())
1a4d82fc
JJ
267 }
268
c1a9b12d 269 probe::WhereClausePick(ref poly_trait_ref) => {
1a4d82fc
JJ
270 // Where clauses can have bound regions in them. We need to instantiate
271 // those to convert from a poly-trait-ref to a trait-ref.
c1a9b12d 272 self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref).substs.clone()
1a4d82fc
JJ
273 }
274 }
275 }
276
277 fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
62682a34 278 F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R,
1a4d82fc
JJ
279 {
280 // If we specified that this is an object method, then the
281 // self-type ought to be something that can be dereferenced to
282 // yield an object-type (e.g., `&Object` or `Box<Object>`
283 // etc).
284
85aaf69f
SL
285 let (_, _, result) = check::autoderef(self.fcx,
286 self.span,
287 self_ty,
288 None,
289 UnresolvedTypeAction::Error,
290 NoPreference,
291 |ty, _| {
292 match ty.sty {
62682a34 293 ty::TyTrait(ref data) => Some(closure(self, ty, &**data)),
85aaf69f
SL
294 _ => None,
295 }
296 });
1a4d82fc
JJ
297
298 match result {
299 Some(r) => r,
300 None => {
301 self.tcx().sess.span_bug(
302 self.span,
303 &format!("self-type `{}` for ObjectPick never dereferenced to an object",
62682a34 304 self_ty))
1a4d82fc
JJ
305 }
306 }
307 }
308
309 fn instantiate_method_substs(&mut self,
310 pick: &probe::Pick<'tcx>,
c1a9b12d
SL
311 supplied_method_types: Vec<Ty<'tcx>>,
312 substs: subst::Substs<'tcx>)
313 -> subst::Substs<'tcx>
1a4d82fc
JJ
314 {
315 // Determine the values for the generic parameters of the method.
316 // If they were not explicitly supplied, just construct fresh
317 // variables.
318 let num_supplied_types = supplied_method_types.len();
c1a9b12d
SL
319 let method = pick.item.as_opt_method().unwrap();
320 let method_types = method.generics.types.get_slice(subst::FnSpace);
321 let num_method_types = method_types.len();
322
1a4d82fc
JJ
323
324 // Create subst for early-bound lifetime parameters, combining
325 // parameters from the type and those from the method.
326 //
327 // FIXME -- permit users to manually specify lifetimes
328 let method_regions =
329 self.fcx.infcx().region_vars_for_defs(
330 self.span,
d9579d0f
AL
331 pick.item.as_opt_method().unwrap()
332 .generics.regions.get_slice(subst::FnSpace));
1a4d82fc 333
c1a9b12d
SL
334 let subst::Substs { types, regions } = substs;
335 let regions = regions.map(|r| r.with_vec(subst::FnSpace, method_regions));
336 let mut final_substs = subst::Substs { types: types, regions: regions };
337
338 if num_supplied_types == 0 {
339 self.fcx.infcx().type_vars_for_defs(
340 self.span,
341 subst::FnSpace,
342 &mut final_substs,
343 method_types);
344 } else if num_method_types == 0 {
345 span_err!(self.tcx().sess, self.span, E0035,
346 "does not take type parameters");
347 self.fcx.infcx().type_vars_for_defs(
348 self.span,
349 subst::FnSpace,
350 &mut final_substs,
351 method_types);
352 } else if num_supplied_types != num_method_types {
353 span_err!(self.tcx().sess, self.span, E0036,
354 "incorrect number of type parameters given for this method");
355 final_substs.types.replace(
356 subst::FnSpace,
357 vec![self.tcx().types.err; num_method_types]);
358 } else {
359 final_substs.types.replace(subst::FnSpace, supplied_method_types);
360 }
361
362 return final_substs;
1a4d82fc
JJ
363 }
364
365 fn unify_receivers(&mut self,
366 self_ty: Ty<'tcx>,
367 method_self_ty: Ty<'tcx>)
368 {
369 match self.fcx.mk_subty(false, infer::Misc(self.span), self_ty, method_self_ty) {
370 Ok(_) => {}
371 Err(_) => {
372 self.tcx().sess.span_bug(
373 self.span,
62682a34
SL
374 &format!("{} was a subtype of {} but now is not?",
375 self_ty, method_self_ty));
1a4d82fc
JJ
376 }
377 }
378 }
379
380 ///////////////////////////////////////////////////////////////////////////
381 //
382
383 fn instantiate_method_sig(&mut self,
384 pick: &probe::Pick<'tcx>,
385 all_substs: subst::Substs<'tcx>)
386 -> InstantiatedMethodSig<'tcx>
387 {
62682a34
SL
388 debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
389 pick,
390 all_substs);
1a4d82fc
JJ
391
392 // Instantiate the bounds on the method with the
c34b1796
AL
393 // type/early-bound-regions substitutions performed. There can
394 // be no late-bound regions appearing here.
d9579d0f
AL
395 let method_predicates = pick.item.as_opt_method().unwrap()
396 .predicates.instantiate(self.tcx(), &all_substs);
85aaf69f
SL
397 let method_predicates = self.fcx.normalize_associated_types_in(self.span,
398 &method_predicates);
1a4d82fc 399
62682a34
SL
400 debug!("method_predicates after subst = {:?}",
401 method_predicates);
1a4d82fc
JJ
402
403 // Instantiate late-bound regions and substitute the trait
404 // parameters into the method type to get the actual method type.
405 //
406 // NB: Instantiate late-bound regions first so that
407 // `instantiate_type_scheme` can normalize associated types that
408 // may reference those regions.
d9579d0f
AL
409 let method_sig = self.replace_late_bound_regions_with_fresh_var(
410 &pick.item.as_opt_method().unwrap().fty.sig);
62682a34
SL
411 debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
412 method_sig);
1a4d82fc
JJ
413
414 let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig);
62682a34
SL
415 debug!("type scheme substituted, method_sig={:?}",
416 method_sig);
1a4d82fc
JJ
417
418 InstantiatedMethodSig {
419 method_sig: method_sig,
420 all_substs: all_substs,
85aaf69f 421 method_predicates: method_predicates,
1a4d82fc
JJ
422 }
423 }
424
425 fn add_obligations(&mut self,
b039eaaf 426 fty: Ty<'tcx>,
1a4d82fc 427 all_substs: &subst::Substs<'tcx>,
85aaf69f 428 method_predicates: &ty::InstantiatedPredicates<'tcx>) {
b039eaaf
SL
429 debug!("add_obligations: fty={:?} all_substs={:?} method_predicates={:?}",
430 fty,
62682a34
SL
431 all_substs,
432 method_predicates);
1a4d82fc
JJ
433
434 self.fcx.add_obligations_for_parameters(
435 traits::ObligationCause::misc(self.span, self.fcx.body_id),
85aaf69f 436 method_predicates);
1a4d82fc 437
e9174d1e
SL
438 // this is a projection from a trait reference, so we have to
439 // make sure that the trait reference inputs are well-formed.
440 self.fcx.add_wf_bounds(
1a4d82fc
JJ
441 all_substs,
442 self.call_expr);
b039eaaf
SL
443
444 // the function type must also be well-formed (this is not
445 // implied by the substs being well-formed because of inherent
446 // impls and late-bound regions - see issue #28609).
447 self.fcx.register_wf_obligation(fty, self.span, traits::MiscObligation);
1a4d82fc
JJ
448 }
449
450 ///////////////////////////////////////////////////////////////////////////
451 // RECONCILIATION
452
453 /// When we select a method with an `&mut self` receiver, we have to go convert any
454 /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut`
455 /// respectively.
456 fn fixup_derefs_on_method_receiver_if_necessary(&self,
c1a9b12d 457 method_callee: &ty::MethodCallee) {
1a4d82fc 458 let sig = match method_callee.ty.sty {
62682a34 459 ty::TyBareFn(_, ref f) => f.sig.clone(),
1a4d82fc
JJ
460 _ => return,
461 };
462
463 match sig.0.inputs[0].sty {
c1a9b12d 464 ty::TyRef(_, ty::TypeAndMut {
1a4d82fc 465 ty: _,
e9174d1e 466 mutbl: hir::MutMutable,
1a4d82fc
JJ
467 }) => {}
468 _ => return,
469 }
470
471 // Gather up expressions we want to munge.
472 let mut exprs = Vec::new();
473 exprs.push(self.self_expr);
474 loop {
475 let last = exprs[exprs.len() - 1];
476 match last.node {
e9174d1e
SL
477 hir::ExprField(ref expr, _) |
478 hir::ExprTupField(ref expr, _) |
479 hir::ExprIndex(ref expr, _) |
480 hir::ExprUnary(hir::UnDeref, ref expr) => exprs.push(&**expr),
1a4d82fc
JJ
481 _ => break,
482 }
483 }
484
62682a34
SL
485 debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={:?}",
486 exprs);
1a4d82fc
JJ
487
488 // Fix up autoderefs and derefs.
489 for (i, &expr) in exprs.iter().rev().enumerate() {
490 // Count autoderefs.
491 let autoderef_count = match self.fcx
492 .inh
c1a9b12d 493 .tables
1a4d82fc 494 .borrow()
c1a9b12d 495 .adjustments
1a4d82fc 496 .get(&expr.id) {
e9174d1e 497 Some(&AdjustDerefRef(ref adj)) => adj.autoderefs,
1a4d82fc
JJ
498 Some(_) | None => 0,
499 };
500
62682a34
SL
501 debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={:?} \
502 autoderef_count={}",
503 i, expr, autoderef_count);
1a4d82fc
JJ
504
505 if autoderef_count > 0 {
506 check::autoderef(self.fcx,
507 expr.span,
508 self.fcx.expr_ty(expr),
509 Some(expr),
85aaf69f 510 UnresolvedTypeAction::Error,
1a4d82fc
JJ
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 {
e9174d1e 524 hir::ExprIndex(ref base_expr, ref index_expr) => {
1a4d82fc
JJ
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.
c1a9b12d
SL
533 let adj = self.fcx.inh.tables.borrow().adjustments.get(&base_expr.id)
534 .cloned();
9346a6ac 535 let (autoderefs, unsize) = match adj {
e9174d1e 536 Some(AdjustDerefRef(adr)) => match adr.autoref {
9346a6ac
AL
537 None => {
538 assert!(adr.unsize.is_none());
539 (adr.autoderefs, None)
540 }
e9174d1e 541 Some(AutoPtr(_, _)) => {
9346a6ac 542 (adr.autoderefs, adr.unsize.map(|target| {
e9174d1e 543 target.builtin_deref(false, NoPreference)
c1a9b12d 544 .expect("fixup: AutoPtr is not &T").ty
9346a6ac
AL
545 }))
546 }
547 Some(_) => {
548 self.tcx().sess.span_bug(
549 base_expr.span,
62682a34
SL
550 &format!("unexpected adjustment autoref {:?}",
551 adr));
9346a6ac
AL
552 }
553 },
554 None => (0, None),
1a4d82fc
JJ
555 Some(_) => {
556 self.tcx().sess.span_bug(
557 base_expr.span,
9346a6ac 558 "unexpected adjustment type");
1a4d82fc
JJ
559 }
560 };
561
9346a6ac
AL
562 let (adjusted_base_ty, unsize) = if let Some(target) = unsize {
563 (target, true)
564 } else {
565 (self.fcx.adjust_expr_ty(base_expr,
e9174d1e 566 Some(&AdjustDerefRef(AutoDerefRef {
9346a6ac
AL
567 autoderefs: autoderefs,
568 autoref: None,
569 unsize: None
570 }))), false)
571 };
1a4d82fc
JJ
572 let index_expr_ty = self.fcx.expr_ty(&**index_expr);
573
574 let result = check::try_index_step(
575 self.fcx,
c1a9b12d 576 ty::MethodCall::expr(expr.id),
1a4d82fc
JJ
577 expr,
578 &**base_expr,
579 adjusted_base_ty,
9346a6ac
AL
580 autoderefs,
581 unsize,
1a4d82fc
JJ
582 PreferMutLvalue,
583 index_expr_ty);
584
585 if let Some((input_ty, return_ty)) = result {
586 demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
587
588 let expr_ty = self.fcx.expr_ty(&*expr);
589 demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
590 }
591 }
e9174d1e 592 hir::ExprUnary(hir::UnDeref, ref base_expr) => {
1a4d82fc
JJ
593 // if this is an overloaded deref, then re-evaluate with
594 // a preference for mut
c1a9b12d
SL
595 let method_call = ty::MethodCall::expr(expr.id);
596 if self.fcx.inh.tables.borrow().method_map.contains_key(&method_call) {
1a4d82fc
JJ
597 check::try_overloaded_deref(
598 self.fcx,
599 expr.span,
600 Some(method_call),
601 Some(&**base_expr),
602 self.fcx.expr_ty(&**base_expr),
603 PreferMutLvalue);
604 }
605 }
606 _ => {}
607 }
608 }
609 }
610 }
611
612 ///////////////////////////////////////////////////////////////////////////
613 // MISCELLANY
614
615 fn tcx(&self) -> &'a ty::ctxt<'tcx> {
616 self.fcx.tcx()
617 }
618
619 fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
620 self.fcx.infcx()
621 }
622
623 fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) {
624 // Disallow calls to the method `drop` defined in the `Drop` trait.
d9579d0f 625 match pick.item.container() {
1a4d82fc
JJ
626 ty::TraitContainer(trait_def_id) => {
627 callee::check_legal_trait_for_method_call(self.fcx.ccx, self.span, trait_def_id)
628 }
e9174d1e 629 ty::ImplContainer(..) => {}
1a4d82fc
JJ
630 }
631 }
632
633 fn upcast(&mut self,
634 source_trait_ref: ty::PolyTraitRef<'tcx>,
e9174d1e 635 target_trait_def_id: DefId)
1a4d82fc
JJ
636 -> ty::PolyTraitRef<'tcx>
637 {
c34b1796
AL
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,
62682a34
SL
646 &format!("cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
647 source_trait_ref,
648 target_trait_def_id,
649 upcast_trait_refs));
1a4d82fc 650 }
c34b1796
AL
651
652 upcast_trait_refs.into_iter().next().unwrap()
1a4d82fc
JJ
653 }
654
655 fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
62682a34 656 where T : TypeFoldable<'tcx>
1a4d82fc
JJ
657 {
658 self.infcx().replace_late_bound_regions_with_fresh_var(
659 self.span, infer::FnCall, value).0
660 }
661}