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 middle::subst::{mod, Subst};
15 use middle::ty::{mod, Ty};
16 use middle::typeck::check::{mod, FnCtxt, NoPreference, PreferMutLvalue};
17 use middle::typeck::{MethodCall, MethodCallee, MethodObject, MethodOrigin,
18 MethodParam, MethodStatic, MethodTraitObject, MethodTypeParam};
19 use middle::typeck::infer::{mod, InferCtxt};
20 use middle::ty_fold::HigherRankedFoldable;
22 use syntax::codemap::Span;
25 use util::ppaux::Repr;
27 struct ConfirmContext<'a, 'tcx:'a> {
28 fcx: &'a FnCtxt<'a, 'tcx>,
30 self_expr: &'a ast::Expr,
31 call_expr: &'a ast::Expr,
34 struct InstantiatedMethodSig<'tcx> {
35 /// Function signature of the method being invoked. The 0th
36 /// argument is the receiver.
37 method_sig: ty::FnSig<'tcx>,
39 /// Substitutions for all types/early-bound-regions declared on
41 all_substs: subst::Substs<'tcx>,
43 /// Substitution to use when adding obligations from the method
44 /// bounds. Normally equal to `all_substs` except for object
45 /// receivers. See FIXME in instantiate_method_sig() for
47 method_bounds_substs: subst::Substs<'tcx>,
49 /// Generic bounds on the method's parameters which must be added
50 /// as pending obligations.
51 method_bounds: ty::GenericBounds<'tcx>,
54 pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
56 self_expr: &ast::Expr,
57 call_expr: &ast::Expr,
58 unadjusted_self_ty: Ty<'tcx>,
59 pick: probe::Pick<'tcx>,
60 supplied_method_types: Vec<Ty<'tcx>>)
63 debug!("confirm(unadjusted_self_ty={}, pick={}, supplied_method_types={})",
64 unadjusted_self_ty.repr(fcx.tcx()),
66 supplied_method_types.repr(fcx.tcx()));
68 let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr, call_expr);
69 confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types)
72 impl<'a,'tcx> ConfirmContext<'a,'tcx> {
73 fn new(fcx: &'a FnCtxt<'a, 'tcx>,
75 self_expr: &'a ast::Expr,
76 call_expr: &'a ast::Expr)
77 -> ConfirmContext<'a, 'tcx>
79 ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
83 unadjusted_self_ty: Ty<'tcx>,
84 pick: probe::Pick<'tcx>,
85 supplied_method_types: Vec<Ty<'tcx>>)
88 // Adjust the self expression the user provided and obtain the adjusted type.
89 let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick.adjustment);
91 // Make sure nobody calls `drop()` explicitly.
92 self.enforce_drop_trait_limitations(&pick);
94 // Create substitutions for the method's type parameters.
95 let (rcvr_substs, method_origin) =
96 self.fresh_receiver_substs(self_ty, &pick);
97 let (method_types, method_regions) =
98 self.instantiate_method_substs(&pick, supplied_method_types);
99 let all_substs = rcvr_substs.with_method(method_types, method_regions);
100 debug!("all_substs={}", all_substs.repr(self.tcx()));
102 // Create the final signature for the method, replacing late-bound regions.
103 let InstantiatedMethodSig {
104 method_sig, all_substs, method_bounds_substs, method_bounds
105 } = self.instantiate_method_sig(&pick, all_substs);
106 let method_self_ty = method_sig.inputs[0];
108 // Unify the (adjusted) self type with what the method expects.
109 self.unify_receivers(self_ty, method_self_ty);
111 // Add any trait/regions obligations specified on the method's type parameters.
112 self.add_obligations(&pick, &method_bounds_substs, &method_bounds);
114 // Create the final `MethodCallee`.
115 let fty = ty::mk_bare_fn(self.tcx(), ty::BareFnTy {
117 fn_style: pick.method_ty.fty.fn_style,
118 abi: pick.method_ty.fty.abi.clone(),
120 let callee = MethodCallee {
121 origin: method_origin,
126 // If this is an `&mut self` method, bias the receiver
127 // expression towards mutability (this will switch
128 // e.g. `Deref` to `DerefMut` in oveloaded derefs and so on).
129 self.fixup_derefs_on_method_receiver_if_necessary(&callee);
134 ///////////////////////////////////////////////////////////////////////////
137 fn adjust_self_ty(&mut self,
138 unadjusted_self_ty: Ty<'tcx>,
139 adjustment: &probe::PickAdjustment)
142 // Construct the actual adjustment and write it into the table
143 let auto_deref_ref = self.create_ty_adjustment(adjustment);
145 // Commit the autoderefs by calling `autoderef again, but this
146 // time writing the results into the various tables.
147 let (autoderefd_ty, n, result) =
149 self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr.id), NoPreference,
150 |_, n| if n == auto_deref_ref.autoderefs { Some(()) } else { None });
151 assert_eq!(n, auto_deref_ref.autoderefs);
152 assert_eq!(result, Some(()));
155 ty::adjust_ty_for_autoref(self.tcx(), self.span, autoderefd_ty,
156 auto_deref_ref.autoref.as_ref());
158 // Write out the final adjustment.
159 self.fcx.write_adjustment(self.self_expr.id, self.span, ty::AdjustDerefRef(auto_deref_ref));
164 fn create_ty_adjustment(&mut self,
165 adjustment: &probe::PickAdjustment)
166 -> ty::AutoDerefRef<'tcx>
169 probe::AutoDeref(num) => {
175 probe::AutoUnsizeLength(autoderefs, len) => {
177 autoderefs: autoderefs,
178 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(len)))
181 probe::AutoRef(mutability, ref sub_adjustment) => {
182 let deref = self.create_ty_adjustment(&**sub_adjustment);
183 let region = self.infcx().next_region_var(infer::Autoref(self.span));
184 wrap_autoref(deref, |base| ty::AutoPtr(region, mutability, base))
189 ///////////////////////////////////////////////////////////////////////////
192 fn fresh_receiver_substs(&mut self,
194 pick: &probe::Pick<'tcx>)
195 -> (subst::Substs<'tcx>, MethodOrigin<'tcx>)
198 * Returns a set of substitutions for the method *receiver*
199 * where all type and region parameters are instantiated with
200 * 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
204 * from the impl level. If so, these are instantiated later in
205 * the `instantiate_method_sig` routine.
209 probe::InherentImplPick(impl_def_id) => {
210 assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(),
211 "impl {} is not an inherent impl", impl_def_id);
212 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
214 (impl_polytype.substs, MethodStatic(pick.method_ty.def_id))
217 probe::ObjectPick(trait_def_id, method_num, real_index) => {
218 self.extract_trait_ref(self_ty, |this, object_ty, data| {
219 // The object data has no entry for the Self
220 // Type. For the purposes of this method call, we
221 // substitute the object type itself. This
222 // wouldn't be a sound substitution in all cases,
223 // since each instance of the object type is a
224 // different existential and hence could match
225 // distinct types (e.g., if `Self` appeared as an
226 // argument type), but those cases have already
227 // been ruled out when we deemed the trait to be
229 let substs = data.principal.substs.clone().with_self_ty(object_ty);
230 let original_trait_ref =
231 Rc::new(ty::TraitRef::new(data.principal.def_id, substs));
232 let upcast_trait_ref = this.upcast(original_trait_ref.clone(), trait_def_id);
233 debug!("original_trait_ref={} upcast_trait_ref={} target_trait={}",
234 original_trait_ref.repr(this.tcx()),
235 upcast_trait_ref.repr(this.tcx()),
236 trait_def_id.repr(this.tcx()));
237 let substs = upcast_trait_ref.substs.clone();
238 let origin = MethodTraitObject(MethodObject {
239 trait_ref: upcast_trait_ref,
240 object_trait_id: trait_def_id,
241 method_num: method_num,
242 real_index: real_index,
248 probe::ExtensionImplPick(impl_def_id, method_num) => {
249 // The method being invoked is the method as defined on the trait,
250 // so return the substitutions from the trait. Consider:
252 // impl<A,B,C> Trait<A,B> for Foo<C> { ... }
254 // If we instantiate A, B, and C with $A, $B, and $C
255 // respectively, then we want to return the type
256 // parameters from the trait ([$A,$B]), not those from
257 // the impl ([$A,$B,$C]) not the receiver type ([$C]).
258 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
259 let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id)
261 .subst(self.tcx(), &impl_polytype.substs);
262 let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
263 method_num: method_num });
264 (impl_trait_ref.substs.clone(), origin)
267 probe::TraitPick(trait_def_id, method_num) => {
268 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
270 // Make a trait reference `$0 : Trait<$1...$n>`
271 // consisting entirely of type variables. Later on in
272 // the process we will unify the transformed-self-type
273 // of the method with the actual type in order to
274 // unify some of these variables.
275 let substs = self.infcx().fresh_substs_for_trait(self.span,
277 self.infcx().next_ty_var());
279 let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, substs.clone()));
280 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
281 method_num: method_num });
285 probe::WhereClausePick(ref trait_ref, method_num) => {
286 let origin = MethodTypeParam(MethodParam { trait_ref: (*trait_ref).clone(),
287 method_num: method_num });
288 (trait_ref.substs.clone(), origin)
293 fn extract_trait_ref<R>(&mut self,
295 closure: |&mut ConfirmContext<'a,'tcx>,
296 Ty<'tcx>, &ty::TyTrait<'tcx>| -> R)
299 // If we specified that this is an object method, then the
300 // self-type ought to be something that can be dereferenced to
301 // yield an object-type (e.g., `&Object` or `Box<Object>`
306 self.fcx, self.span, self_ty, None, NoPreference,
309 ty::ty_trait(ref data) => Some(closure(self, ty, &**data)),
317 self.tcx().sess.span_bug(
319 format!("self-type `{}` for ObjectPick never dereferenced to an object",
320 self_ty.repr(self.tcx()))[])
325 fn instantiate_method_substs(&mut self,
326 pick: &probe::Pick<'tcx>,
327 supplied_method_types: Vec<Ty<'tcx>>)
328 -> (Vec<Ty<'tcx>>, Vec<ty::Region>)
330 // Determine the values for the generic parameters of the method.
331 // If they were not explicitly supplied, just construct fresh
333 let num_supplied_types = supplied_method_types.len();
334 let num_method_types = pick.method_ty.generics.types.len(subst::FnSpace);
336 if num_supplied_types == 0u {
337 self.fcx.infcx().next_ty_vars(num_method_types)
338 } else if num_method_types == 0u {
339 span_err!(self.tcx().sess, self.span, E0035,
340 "does not take type parameters");
341 self.fcx.infcx().next_ty_vars(num_method_types)
342 } else if num_supplied_types != num_method_types {
343 span_err!(self.tcx().sess, self.span, E0036,
344 "incorrect number of type parameters given for this method");
345 Vec::from_elem(num_method_types, ty::mk_err())
347 supplied_method_types
351 // Create subst for early-bound lifetime parameters, combining
352 // parameters from the type and those from the method.
354 // FIXME -- permit users to manually specify lifetimes
356 self.fcx.infcx().region_vars_for_defs(
358 pick.method_ty.generics.regions.get_slice(subst::FnSpace));
360 (method_types, method_regions)
363 fn unify_receivers(&mut self,
365 method_self_ty: Ty<'tcx>)
367 match self.fcx.mk_subty(false, infer::Misc(self.span), self_ty, method_self_ty) {
370 self.tcx().sess.span_bug(
373 "{} was a subtype of {} but now is not?",
374 self_ty.repr(self.tcx()),
375 method_self_ty.repr(self.tcx()))[]);
380 ///////////////////////////////////////////////////////////////////////////
383 fn instantiate_method_sig(&mut self,
384 pick: &probe::Pick<'tcx>,
385 all_substs: subst::Substs<'tcx>)
386 -> InstantiatedMethodSig<'tcx>
388 // If this method comes from an impl (as opposed to a trait),
389 // it may have late-bound regions from the impl that appear in
390 // the substitutions, method signature, and
391 // bounds. Instantiate those at this point. (If it comes from
392 // a trait, this step has no effect, as there are no
393 // late-bound regions to instantiate.)
395 // The binder level here corresponds to the impl.
396 let (all_substs, (method_sig, method_generics)) =
397 self.replace_late_bound_regions_with_fresh_var(
398 &ty::bind((all_substs,
399 (pick.method_ty.fty.sig.clone(),
400 pick.method_ty.generics.clone())))).value;
402 debug!("late-bound lifetimes from impl instantiated, \
403 all_substs={} method_sig={} method_generics={}",
404 all_substs.repr(self.tcx()),
405 method_sig.repr(self.tcx()),
406 method_generics.repr(self.tcx()));
408 // Instantiate the bounds on the method with the
409 // type/early-bound-regions substitutions performed. The only
410 // late-bound-regions that can appear in bounds are from the
411 // impl, and those were already instantiated above.
413 // FIXME(DST). Super hack. For a method on a trait object
414 // `Trait`, the generic signature requires that
415 // `Self:Trait`. Since, for an object, we bind `Self` to the
416 // type `Trait`, this leads to an obligation
417 // `Trait:Trait`. Until such time we DST is fully implemented,
418 // that obligation is not necessarily satisfied. (In the
419 // future, it would be.)
421 // To sidestep this, we overwrite the binding for `Self` with
422 // `err` (just for trait objects) when we generate the
423 // obligations. This causes us to generate the obligation
424 // `err:Trait`, and the error type is considered to implement
425 // all traits, so we're all good. Hack hack hack.
426 let method_bounds_substs = match pick.kind {
427 probe::ObjectPick(..) => {
428 let mut temp_substs = all_substs.clone();
429 temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = ty::mk_err();
437 method_generics.to_bounds(self.tcx(), &method_bounds_substs);
439 debug!("method_bounds after subst = {}",
440 method_bounds.repr(self.tcx()));
442 // Substitute the type/early-bound-regions into the method
443 // signature. In addition, the method signature may bind
444 // late-bound regions, so instantiate those.
445 let method_sig = method_sig.subst(self.tcx(), &all_substs);
446 let method_sig = self.replace_late_bound_regions_with_fresh_var(&method_sig);
448 debug!("late-bound lifetimes from method instantiated, method_sig={}",
449 method_sig.repr(self.tcx()));
451 InstantiatedMethodSig {
452 method_sig: method_sig,
453 all_substs: all_substs,
454 method_bounds_substs: method_bounds_substs,
455 method_bounds: method_bounds,
459 fn add_obligations(&mut self,
460 pick: &probe::Pick<'tcx>,
461 method_bounds_substs: &subst::Substs<'tcx>,
462 method_bounds: &ty::GenericBounds<'tcx>) {
463 debug!("add_obligations: pick={} method_bounds_substs={} method_bounds={}",
464 pick.repr(self.tcx()),
465 method_bounds_substs.repr(self.tcx()),
466 method_bounds.repr(self.tcx()));
468 self.fcx.add_obligations_for_parameters(
469 traits::ObligationCause::misc(self.span),
470 method_bounds_substs,
473 self.fcx.add_default_region_param_bounds(
474 method_bounds_substs,
478 ///////////////////////////////////////////////////////////////////////////
481 fn fixup_derefs_on_method_receiver_if_necessary(&self,
482 method_callee: &MethodCallee) {
484 * When we select a method with an `&mut self` receiver, we have to go
485 * convert any auto-derefs, indices, etc from `Deref` and `Index` into
486 * `DerefMut` and `IndexMut` respectively.
489 let sig = match method_callee.ty.sty {
490 ty::ty_bare_fn(ref f) => f.sig.clone(),
491 ty::ty_closure(ref f) => f.sig.clone(),
495 match sig.inputs[0].sty {
496 ty::ty_rptr(_, ty::mt {
498 mutbl: ast::MutMutable,
503 // Gather up expressions we want to munge.
504 let mut exprs = Vec::new();
505 exprs.push(self.self_expr);
507 let last = exprs[exprs.len() - 1];
509 ast::ExprParen(ref expr) |
510 ast::ExprField(ref expr, _) |
511 ast::ExprTupField(ref expr, _) |
512 ast::ExprSlice(ref expr, _, _, _) |
513 ast::ExprIndex(ref expr, _) |
514 ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr),
519 debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={}",
520 exprs.repr(self.tcx()));
522 // Fix up autoderefs and derefs.
523 for (i, expr) in exprs.iter().rev().enumerate() {
525 let autoderef_count = match self.fcx
530 Some(&ty::AdjustDerefRef(ty::AutoDerefRef {
531 autoderefs: autoderef_count,
533 })) => autoderef_count,
537 debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={} autoderef_count={}",
538 i, expr.repr(self.tcx()), autoderef_count);
540 if autoderef_count > 0 {
541 check::autoderef(self.fcx,
543 self.fcx.expr_ty(*expr),
547 if autoderefs == autoderef_count + 1 {
555 // Don't retry the first one or we might infinite loop!
558 ast::ExprIndex(ref base_expr, _) => {
559 let mut base_adjustment =
560 match self.fcx.inh.adjustments.borrow().get(&base_expr.id) {
561 Some(&ty::AdjustDerefRef(ref adr)) => (*adr).clone(),
562 None => ty::AutoDerefRef { autoderefs: 0, autoref: None },
564 self.tcx().sess.span_bug(
566 "unexpected adjustment type");
570 // If this is an overloaded index, the
571 // adjustment will include an extra layer of
572 // autoref because the method is an &self/&mut
573 // self method. We have to peel it off to get
574 // the raw adjustment that `try_index_step`
575 // expects. This is annoying and horrible. We
576 // ought to recode this routine so it doesn't
577 // (ab)use the normal type checking paths.
578 base_adjustment.autoref = match base_adjustment.autoref {
580 Some(ty::AutoPtr(_, _, None)) => { None }
581 Some(ty::AutoPtr(_, _, Some(box r))) => { Some(r) }
583 self.tcx().sess.span_bug(
585 "unexpected adjustment autoref");
589 let adjusted_base_ty =
590 self.fcx.adjust_expr_ty(
592 Some(&ty::AdjustDerefRef(base_adjustment.clone())));
594 check::try_index_step(
596 MethodCall::expr(expr.id),
603 ast::ExprUnary(ast::UnDeref, ref base_expr) => {
604 // if this is an overloaded deref, then re-evaluate with
605 // a preference for mut
606 let method_call = MethodCall::expr(expr.id);
607 if self.fcx.inh.method_map.borrow().contains_key(&method_call) {
608 check::try_overloaded_deref(
613 self.fcx.expr_ty(&**base_expr),
623 ///////////////////////////////////////////////////////////////////////////
626 fn tcx(&self) -> &'a ty::ctxt<'tcx> {
630 fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
634 fn enforce_drop_trait_limitations(&self, pick: &probe::Pick) {
635 // Disallow calls to the method `drop` defined in the `Drop` trait.
636 match pick.method_ty.container {
637 ty::TraitContainer(trait_def_id) => {
638 if Some(trait_def_id) == self.tcx().lang_items.drop_trait() {
639 span_err!(self.tcx().sess, self.span, E0040,
640 "explicit call to destructor");
643 ty::ImplContainer(..) => {
644 // Since `drop` is a trait method, we expect that any
645 // potential calls to it will wind up in the other
646 // arm. But just to be sure, check that the method id
647 // does not appear in the list of destructors.
648 assert!(!self.tcx().destructors.borrow().contains(&pick.method_ty.def_id));
654 source_trait_ref: Rc<ty::TraitRef<'tcx>>,
655 target_trait_def_id: ast::DefId)
656 -> Rc<ty::TraitRef<'tcx>>
658 for super_trait_ref in traits::supertraits(self.tcx(), source_trait_ref.clone()) {
659 if super_trait_ref.def_id == target_trait_def_id {
660 return super_trait_ref;
664 self.tcx().sess.span_bug(
666 format!("cannot upcast `{}` to `{}`",
667 source_trait_ref.repr(self.tcx()),
668 target_trait_def_id.repr(self.tcx()))[]);
671 fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &T) -> T
672 where T : HigherRankedFoldable<'tcx>
674 self.infcx().replace_late_bound_regions_with_fresh_var(
675 self.span, infer::FnCall, value).0
679 fn wrap_autoref<'tcx>(mut deref: ty::AutoDerefRef<'tcx>,
680 base_fn: |Option<Box<ty::AutoRef<'tcx>>>| -> ty::AutoRef<'tcx>)
681 -> ty::AutoDerefRef<'tcx> {
682 let autoref = mem::replace(&mut deref.autoref, None);
683 let autoref = autoref.map(|r| box r);
684 deref.autoref = Some(base_fn(autoref));