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.
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.
13 use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
14 use check::UnresolvedTypeAction;
15 use middle::mem_categorization::Typer;
16 use middle::subst::{self};
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;
23 use middle::infer::InferCtxt;
25 use syntax::codemap::Span;
28 use std::iter::repeat;
29 use util::ppaux::Repr;
31 struct ConfirmContext<'a, 'tcx:'a> {
32 fcx: &'a FnCtxt<'a, 'tcx>,
34 self_expr: &'tcx ast::Expr,
35 call_expr: &'tcx ast::Expr,
38 struct InstantiatedMethodSig<'tcx> {
39 /// Function signature of the method being invoked. The 0th
40 /// argument is the receiver.
41 method_sig: ty::FnSig<'tcx>,
43 /// Substitutions for all types/early-bound-regions declared on
45 all_substs: subst::Substs<'tcx>,
47 /// Generic bounds on the method's parameters which must be added
48 /// as pending obligations.
49 method_bounds: ty::GenericBounds<'tcx>,
52 pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
54 self_expr: &'tcx ast::Expr,
55 call_expr: &'tcx ast::Expr,
56 unadjusted_self_ty: Ty<'tcx>,
57 pick: probe::Pick<'tcx>,
58 supplied_method_types: Vec<Ty<'tcx>>)
61 debug!("confirm(unadjusted_self_ty={}, pick={}, supplied_method_types={})",
62 unadjusted_self_ty.repr(fcx.tcx()),
64 supplied_method_types.repr(fcx.tcx()));
66 let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr, call_expr);
67 confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types)
70 impl<'a,'tcx> ConfirmContext<'a,'tcx> {
71 fn new(fcx: &'a FnCtxt<'a, 'tcx>,
73 self_expr: &'tcx ast::Expr,
74 call_expr: &'tcx ast::Expr)
75 -> ConfirmContext<'a, 'tcx>
77 ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
81 unadjusted_self_ty: Ty<'tcx>,
82 pick: probe::Pick<'tcx>,
83 supplied_method_types: Vec<Ty<'tcx>>)
86 // Adjust the self expression the user provided and obtain the adjusted type.
87 let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick.adjustment);
89 // Make sure nobody calls `drop()` explicitly.
90 self.enforce_illegal_method_limitations(&pick);
92 // Create substitutions for the method's type parameters.
93 let (rcvr_substs, method_origin) =
94 self.fresh_receiver_substs(self_ty, &pick);
95 let (method_types, method_regions) =
96 self.instantiate_method_substs(&pick, supplied_method_types);
97 let all_substs = rcvr_substs.with_method(method_types, method_regions);
98 debug!("all_substs={}", all_substs.repr(self.tcx()));
100 // Create the final signature for the method, replacing late-bound regions.
101 let InstantiatedMethodSig {
102 method_sig, all_substs, method_bounds
103 } = self.instantiate_method_sig(&pick, all_substs);
104 let method_self_ty = method_sig.inputs[0];
106 // Unify the (adjusted) self type with what the method expects.
107 self.unify_receivers(self_ty, method_self_ty);
109 // Add any trait/regions obligations specified on the method's type parameters.
110 self.add_obligations(&pick, &all_substs, &method_bounds);
112 // Create the final `MethodCallee`.
113 let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy {
114 sig: ty::Binder(method_sig),
115 unsafety: pick.method_ty.fty.unsafety,
116 abi: pick.method_ty.fty.abi.clone(),
118 let callee = MethodCallee {
119 origin: method_origin,
124 // If this is an `&mut self` method, bias the receiver
125 // expression towards mutability (this will switch
126 // e.g. `Deref` to `DerefMut` in overloaded derefs and so on).
127 self.fixup_derefs_on_method_receiver_if_necessary(&callee);
132 ///////////////////////////////////////////////////////////////////////////
135 fn adjust_self_ty(&mut self,
136 unadjusted_self_ty: Ty<'tcx>,
137 adjustment: &probe::PickAdjustment)
140 // Construct the actual adjustment and write it into the table
141 let auto_deref_ref = self.create_ty_adjustment(adjustment);
143 // Commit the autoderefs by calling `autoderef again, but this
144 // time writing the results into the various tables.
145 let (autoderefd_ty, n, result) = check::autoderef(self.fcx,
148 Some(self.self_expr),
149 UnresolvedTypeAction::Error,
152 if n == auto_deref_ref.autoderefs {
158 assert_eq!(n, auto_deref_ref.autoderefs);
159 assert_eq!(result, Some(()));
162 ty::adjust_ty_for_autoref(self.tcx(), self.span, autoderefd_ty,
163 auto_deref_ref.autoref.as_ref());
165 // Write out the final adjustment.
166 self.fcx.write_adjustment(self.self_expr.id, self.span, ty::AdjustDerefRef(auto_deref_ref));
171 fn create_ty_adjustment(&mut self,
172 adjustment: &probe::PickAdjustment)
173 -> ty::AutoDerefRef<'tcx>
176 probe::AutoDeref(num) => {
182 probe::AutoUnsizeLength(autoderefs, len) => {
184 autoderefs: autoderefs,
185 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(len)))
188 probe::AutoRef(mutability, ref sub_adjustment) => {
189 let deref = self.create_ty_adjustment(&**sub_adjustment);
190 let region = self.infcx().next_region_var(infer::Autoref(self.span));
191 wrap_autoref(deref, |base| ty::AutoPtr(region, mutability, base))
196 ///////////////////////////////////////////////////////////////////////////
199 /// Returns a set of substitutions for the method *receiver* where all type and region
200 /// parameters are instantiated with fresh variables. This substitution does not include any
201 /// parameters declared on the method itself.
203 /// Note that this substitution may include late-bound regions from the impl level. If so,
204 /// these are instantiated later in the `instantiate_method_sig` routine.
205 fn fresh_receiver_substs(&mut self,
207 pick: &probe::Pick<'tcx>)
208 -> (subst::Substs<'tcx>, MethodOrigin<'tcx>)
211 probe::InherentImplPick(impl_def_id) => {
212 assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(),
213 "impl {:?} is not an inherent impl", impl_def_id);
214 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
216 (impl_polytype.substs, MethodStatic(pick.method_ty.def_id))
219 probe::ObjectPick(trait_def_id, method_num, vtable_index) => {
220 self.extract_trait_ref(self_ty, |this, object_ty, data| {
221 // The object data has no entry for the Self
222 // Type. For the purposes of this method call, we
223 // substitute the object type itself. This
224 // wouldn't be a sound substitution in all cases,
225 // since each instance of the object type is a
226 // different existential and hence could match
227 // distinct types (e.g., if `Self` appeared as an
228 // argument type), but those cases have already
229 // been ruled out when we deemed the trait to be
231 let original_poly_trait_ref =
232 data.principal_trait_ref_with_self_ty(this.tcx(), object_ty);
233 let upcast_poly_trait_ref =
234 this.upcast(original_poly_trait_ref.clone(), trait_def_id);
235 let upcast_trait_ref =
236 this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
237 debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}",
238 original_poly_trait_ref.repr(this.tcx()),
239 upcast_trait_ref.repr(this.tcx()),
240 trait_def_id.repr(this.tcx()));
241 let substs = upcast_trait_ref.substs.clone();
242 let origin = MethodTraitObject(MethodObject {
243 trait_ref: upcast_trait_ref,
244 object_trait_id: trait_def_id,
245 method_num: method_num,
246 vtable_index: vtable_index,
252 probe::ExtensionImplPick(impl_def_id, method_num) => {
253 // The method being invoked is the method as defined on the trait,
254 // so return the substitutions from the trait. Consider:
256 // impl<A,B,C> Trait<A,B> for Foo<C> { ... }
258 // If we instantiate A, B, and C with $A, $B, and $C
259 // respectively, then we want to return the type
260 // parameters from the trait ([$A,$B]), not those from
261 // the impl ([$A,$B,$C]) not the receiver type ([$C]).
262 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
264 self.fcx.instantiate_type_scheme(
266 &impl_polytype.substs,
267 &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
268 let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
269 method_num: method_num,
270 impl_def_id: Some(impl_def_id) });
271 (impl_trait_ref.substs.clone(), origin)
274 probe::TraitPick(trait_def_id, method_num) => {
275 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
277 // Make a trait reference `$0 : Trait<$1...$n>`
278 // consisting entirely of type variables. Later on in
279 // the process we will unify the transformed-self-type
280 // of the method with the actual type in order to
281 // unify some of these variables.
282 let substs = self.infcx().fresh_substs_for_trait(self.span,
284 self.infcx().next_ty_var());
287 Rc::new(ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone())));
288 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
289 method_num: method_num,
290 impl_def_id: None });
294 probe::WhereClausePick(ref poly_trait_ref, method_num) => {
295 // Where clauses can have bound regions in them. We need to instantiate
296 // those to convert from a poly-trait-ref to a trait-ref.
297 let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
298 let substs = trait_ref.substs.clone();
299 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
300 method_num: method_num,
301 impl_def_id: None });
307 fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
308 F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TyTrait<'tcx>) -> R,
310 // If we specified that this is an object method, then the
311 // self-type ought to be something that can be dereferenced to
312 // yield an object-type (e.g., `&Object` or `Box<Object>`
315 let (_, _, result) = check::autoderef(self.fcx,
319 UnresolvedTypeAction::Error,
323 ty::ty_trait(ref data) => Some(closure(self, ty, &**data)),
331 self.tcx().sess.span_bug(
333 &format!("self-type `{}` for ObjectPick never dereferenced to an object",
334 self_ty.repr(self.tcx()))[])
339 fn instantiate_method_substs(&mut self,
340 pick: &probe::Pick<'tcx>,
341 supplied_method_types: Vec<Ty<'tcx>>)
342 -> (Vec<Ty<'tcx>>, Vec<ty::Region>)
344 // Determine the values for the generic parameters of the method.
345 // If they were not explicitly supplied, just construct fresh
347 let num_supplied_types = supplied_method_types.len();
348 let num_method_types = pick.method_ty.generics.types.len(subst::FnSpace);
350 if num_supplied_types == 0 {
351 self.fcx.infcx().next_ty_vars(num_method_types)
352 } else if num_method_types == 0 {
353 span_err!(self.tcx().sess, self.span, E0035,
354 "does not take type parameters");
355 self.fcx.infcx().next_ty_vars(num_method_types)
356 } else if num_supplied_types != num_method_types {
357 span_err!(self.tcx().sess, self.span, E0036,
358 "incorrect number of type parameters given for this method");
359 repeat(self.tcx().types.err).take(num_method_types).collect()
361 supplied_method_types
365 // Create subst for early-bound lifetime parameters, combining
366 // parameters from the type and those from the method.
368 // FIXME -- permit users to manually specify lifetimes
370 self.fcx.infcx().region_vars_for_defs(
372 pick.method_ty.generics.regions.get_slice(subst::FnSpace));
374 (method_types, method_regions)
377 fn unify_receivers(&mut self,
379 method_self_ty: Ty<'tcx>)
381 match self.fcx.mk_subty(false, infer::Misc(self.span), self_ty, method_self_ty) {
384 self.tcx().sess.span_bug(
387 "{} was a subtype of {} but now is not?",
388 self_ty.repr(self.tcx()),
389 method_self_ty.repr(self.tcx()))[]);
394 ///////////////////////////////////////////////////////////////////////////
397 fn instantiate_method_sig(&mut self,
398 pick: &probe::Pick<'tcx>,
399 all_substs: subst::Substs<'tcx>)
400 -> InstantiatedMethodSig<'tcx>
402 debug!("instantiate_method_sig(pick={}, all_substs={})",
403 pick.repr(self.tcx()),
404 all_substs.repr(self.tcx()));
406 // Instantiate the bounds on the method with the
407 // type/early-bound-regions substitutions performed. The only
408 // late-bound-regions that can appear in bounds are from the
409 // impl, and those were already instantiated above.
411 // FIXME(DST). Super hack. For a method on a trait object
412 // `Trait`, the generic signature requires that
413 // `Self:Trait`. Since, for an object, we bind `Self` to the
414 // type `Trait`, this leads to an obligation
415 // `Trait:Trait`. Until such time we DST is fully implemented,
416 // that obligation is not necessarily satisfied. (In the
417 // future, it would be.) But we know that the true `Self` DOES implement
418 // the trait. So we just delete this requirement. Hack hack hack.
419 let mut method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &all_substs);
421 probe::ObjectPick(..) => {
422 assert_eq!(method_bounds.predicates.get_slice(subst::SelfSpace).len(), 1);
423 method_bounds.predicates.pop(subst::SelfSpace);
427 let method_bounds = self.fcx.normalize_associated_types_in(self.span, &method_bounds);
429 debug!("method_bounds after subst = {}",
430 method_bounds.repr(self.tcx()));
432 // Instantiate late-bound regions and substitute the trait
433 // parameters into the method type to get the actual method type.
435 // NB: Instantiate late-bound regions first so that
436 // `instantiate_type_scheme` can normalize associated types that
437 // may reference those regions.
438 let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.method_ty.fty.sig);
439 debug!("late-bound lifetimes from method instantiated, method_sig={}",
440 method_sig.repr(self.tcx()));
442 let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig);
443 debug!("type scheme substituted, method_sig={}",
444 method_sig.repr(self.tcx()));
446 InstantiatedMethodSig {
447 method_sig: method_sig,
448 all_substs: all_substs,
449 method_bounds: method_bounds,
453 fn add_obligations(&mut self,
454 pick: &probe::Pick<'tcx>,
455 all_substs: &subst::Substs<'tcx>,
456 method_bounds: &ty::GenericBounds<'tcx>) {
457 debug!("add_obligations: pick={} all_substs={} method_bounds={}",
458 pick.repr(self.tcx()),
459 all_substs.repr(self.tcx()),
460 method_bounds.repr(self.tcx()));
462 self.fcx.add_obligations_for_parameters(
463 traits::ObligationCause::misc(self.span, self.fcx.body_id),
466 self.fcx.add_default_region_param_bounds(
471 ///////////////////////////////////////////////////////////////////////////
474 /// When we select a method with an `&mut self` receiver, we have to go convert any
475 /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut`
477 fn fixup_derefs_on_method_receiver_if_necessary(&self,
478 method_callee: &MethodCallee) {
479 let sig = match method_callee.ty.sty {
480 ty::ty_bare_fn(_, ref f) => f.sig.clone(),
484 match sig.0.inputs[0].sty {
485 ty::ty_rptr(_, ty::mt {
487 mutbl: ast::MutMutable,
492 // Gather up expressions we want to munge.
493 let mut exprs = Vec::new();
494 exprs.push(self.self_expr);
496 let last = exprs[exprs.len() - 1];
498 ast::ExprParen(ref expr) |
499 ast::ExprField(ref expr, _) |
500 ast::ExprTupField(ref expr, _) |
501 ast::ExprIndex(ref expr, _) |
502 ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr),
507 debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={}",
508 exprs.repr(self.tcx()));
510 // Fix up autoderefs and derefs.
511 for (i, &expr) in exprs.iter().rev().enumerate() {
513 let autoderef_count = match self.fcx
518 Some(&ty::AdjustDerefRef(ty::AutoDerefRef {
519 autoderefs: autoderef_count,
521 })) => autoderef_count,
525 debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={} autoderef_count={}",
526 i, expr.repr(self.tcx()), autoderef_count);
528 if autoderef_count > 0 {
529 check::autoderef(self.fcx,
531 self.fcx.expr_ty(expr),
533 UnresolvedTypeAction::Error,
536 if autoderefs == autoderef_count + 1 {
544 // Don't retry the first one or we might infinite loop!
547 ast::ExprIndex(ref base_expr, ref index_expr) => {
548 let mut base_adjustment =
549 match self.fcx.inh.adjustments.borrow().get(&base_expr.id) {
550 Some(&ty::AdjustDerefRef(ref adr)) => (*adr).clone(),
551 None => ty::AutoDerefRef { autoderefs: 0, autoref: None },
553 self.tcx().sess.span_bug(
555 "unexpected adjustment type");
559 // If this is an overloaded index, the
560 // adjustment will include an extra layer of
561 // autoref because the method is an &self/&mut
562 // self method. We have to peel it off to get
563 // the raw adjustment that `try_index_step`
564 // expects. This is annoying and horrible. We
565 // ought to recode this routine so it doesn't
566 // (ab)use the normal type checking paths.
567 base_adjustment.autoref = match base_adjustment.autoref {
569 Some(ty::AutoPtr(_, _, None)) => { None }
570 Some(ty::AutoPtr(_, _, Some(box r))) => { Some(r) }
572 self.tcx().sess.span_bug(
574 "unexpected adjustment autoref");
578 let adjusted_base_ty =
579 self.fcx.adjust_expr_ty(
581 Some(&ty::AdjustDerefRef(base_adjustment.clone())));
582 let index_expr_ty = self.fcx.expr_ty(&**index_expr);
584 let result = check::try_index_step(
586 MethodCall::expr(expr.id),
594 if let Some((input_ty, return_ty)) = result {
595 demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
597 let expr_ty = self.fcx.expr_ty(&*expr);
598 demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
601 ast::ExprUnary(ast::UnDeref, ref base_expr) => {
602 // if this is an overloaded deref, then re-evaluate with
603 // a preference for mut
604 let method_call = MethodCall::expr(expr.id);
605 if self.fcx.inh.method_map.borrow().contains_key(&method_call) {
606 check::try_overloaded_deref(
611 self.fcx.expr_ty(&**base_expr),
621 ///////////////////////////////////////////////////////////////////////////
624 fn tcx(&self) -> &'a ty::ctxt<'tcx> {
628 fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
632 fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) {
633 // Disallow calls to the method `drop` defined in the `Drop` trait.
634 match pick.method_ty.container {
635 ty::TraitContainer(trait_def_id) => {
636 callee::check_legal_trait_for_method_call(self.fcx.ccx, self.span, trait_def_id)
638 ty::ImplContainer(..) => {
639 // Since `drop` is a trait method, we expect that any
640 // potential calls to it will wind up in the other
641 // arm. But just to be sure, check that the method id
642 // does not appear in the list of destructors.
643 assert!(!self.tcx().destructors.borrow().contains(&pick.method_ty.def_id));
649 source_trait_ref: ty::PolyTraitRef<'tcx>,
650 target_trait_def_id: ast::DefId)
651 -> ty::PolyTraitRef<'tcx>
653 match traits::upcast(self.tcx(), source_trait_ref.clone(), target_trait_def_id) {
654 Some(super_trait_ref) => super_trait_ref,
656 self.tcx().sess.span_bug(
658 &format!("cannot upcast `{}` to `{}`",
659 source_trait_ref.repr(self.tcx()),
660 target_trait_def_id.repr(self.tcx())));
665 fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
666 where T : TypeFoldable<'tcx> + Repr<'tcx>
668 self.infcx().replace_late_bound_regions_with_fresh_var(
669 self.span, infer::FnCall, value).0
673 fn wrap_autoref<'tcx, F>(mut deref: ty::AutoDerefRef<'tcx>,
675 -> ty::AutoDerefRef<'tcx> where
676 F: FnOnce(Option<Box<ty::AutoRef<'tcx>>>) -> ty::AutoRef<'tcx>,
678 let autoref = mem::replace(&mut deref.autoref, None);
679 let autoref = autoref.map(|r| box r);
680 deref.autoref = Some(base_fn(autoref));