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.
11 use super::{MethodError,Ambiguity,NoMatch};
12 use super::MethodIndex;
13 use super::{CandidateSource,ImplSource,TraitSource};
16 use check::{FnCtxt, NoPreference};
17 use middle::fast_reject;
19 use middle::subst::Subst;
21 use middle::ty::{mod, Ty, ToPolyTraitRef};
22 use middle::ty_fold::TypeFoldable;
24 use middle::infer::InferCtxt;
26 use syntax::codemap::{Span, DUMMY_SP};
27 use std::collections::HashSet;
29 use util::ppaux::Repr;
31 use self::CandidateKind::*;
32 pub use self::PickAdjustment::*;
33 pub use self::PickKind::*;
35 struct ProbeContext<'a, 'tcx:'a> {
36 fcx: &'a FnCtxt<'a, 'tcx>,
38 method_name: ast::Name,
39 steps: Rc<Vec<CandidateStep<'tcx>>>,
40 opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>,
41 inherent_candidates: Vec<Candidate<'tcx>>,
42 extension_candidates: Vec<Candidate<'tcx>>,
43 impl_dups: HashSet<ast::DefId>,
44 static_candidates: Vec<CandidateSource>,
47 struct CandidateStep<'tcx> {
49 adjustment: PickAdjustment,
52 struct Candidate<'tcx> {
53 xform_self_ty: Ty<'tcx>,
54 method_ty: Rc<ty::Method<'tcx>>,
55 kind: CandidateKind<'tcx>,
58 enum CandidateKind<'tcx> {
59 InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>),
60 ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint),
61 ExtensionImplCandidate(/* Impl */ ast::DefId, Rc<ty::TraitRef<'tcx>>,
62 subst::Substs<'tcx>, MethodIndex),
63 UnboxedClosureCandidate(/* Trait */ ast::DefId, MethodIndex),
64 WhereClauseCandidate(ty::PolyTraitRef<'tcx>, MethodIndex),
67 pub struct Pick<'tcx> {
68 pub method_ty: Rc<ty::Method<'tcx>>,
69 pub adjustment: PickAdjustment,
70 pub kind: PickKind<'tcx>,
73 #[deriving(Clone,Show)]
74 pub enum PickKind<'tcx> {
75 InherentImplPick(/* Impl */ ast::DefId),
76 ObjectPick(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint),
77 ExtensionImplPick(/* Impl */ ast::DefId, MethodIndex),
78 TraitPick(/* Trait */ ast::DefId, MethodIndex),
79 WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>, MethodIndex),
82 pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError>;
84 // This is a kind of "abstracted" version of ty::AutoAdjustment. The
85 // difference is that it doesn't embed any regions or other
86 // specifics. The "confirmation" step recreates those details as
88 #[deriving(Clone,Show)]
89 pub enum PickAdjustment {
90 // Indicates that the source expression should be autoderef'd N times
92 // A = expr | *expr | **expr
95 // Indicates that the source expression should be autoderef'd N
96 // times and then "unsized". This should probably eventually go
97 // away in favor of just coercing method receivers.
99 // A = unsize(expr | *expr | **expr)
100 AutoUnsizeLength(/* number of autoderefs */ uint, /* length*/ uint),
102 // Indicates that an autoref is applied after some number of other adjustments
105 AutoRef(ast::Mutability, Box<PickAdjustment>),
108 pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
110 method_name: ast::Name,
112 call_expr_id: ast::NodeId)
115 debug!("probe(self_ty={}, method_name={}, call_expr_id={})",
116 self_ty.repr(fcx.tcx()),
120 // FIXME(#18741) -- right now, creating the steps involves evaluating the
121 // `*` operator, which registers obligations that then escape into
122 // the global fulfillment context and thus has global
123 // side-effects. This is a bit of a pain to refactor. So just let
124 // it ride, although it's really not great, and in fact could I
125 // think cause spurious errors. Really though this part should
126 // take place in the `fcx.infcx().probe` below.
127 let steps = match create_steps(fcx, span, self_ty) {
128 Some(steps) => steps,
129 None => return Err(NoMatch(Vec::new())),
132 // Create a list of simplified self types, if we can.
133 let mut simplified_steps = Vec::new();
134 for step in steps.iter() {
135 match fast_reject::simplify_type(fcx.tcx(), step.self_ty, true) {
137 Some(simplified_type) => { simplified_steps.push(simplified_type); }
140 let opt_simplified_steps =
141 if simplified_steps.len() < steps.len() {
142 None // failed to convert at least one of the steps
144 Some(simplified_steps)
147 debug!("ProbeContext: steps for self_ty={} are {}",
148 self_ty.repr(fcx.tcx()),
149 steps.repr(fcx.tcx()));
151 // this creates one big transaction so that all type variables etc
152 // that we create during the probe process are removed later
153 let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures
154 fcx.infcx().probe(|_| {
155 let (steps, opt_simplified_steps) = dummy.take().unwrap();
156 let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps);
157 probe_cx.assemble_inherent_candidates();
158 probe_cx.assemble_extension_candidates_for_traits_in_scope(call_expr_id);
163 fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
166 -> Option<Vec<CandidateStep<'tcx>>> {
167 let mut steps = Vec::new();
169 let (fully_dereferenced_ty, dereferences, _) =
171 fcx, span, self_ty, None, NoPreference,
173 let adjustment = AutoDeref(d);
174 steps.push(CandidateStep { self_ty: t, adjustment: adjustment });
175 None::<()> // keep iterating until we can't anymore
178 match fully_dereferenced_ty.sty {
179 ty::ty_vec(elem_ty, Some(len)) => {
180 steps.push(CandidateStep {
181 self_ty: ty::mk_vec(fcx.tcx(), elem_ty, None),
182 adjustment: AutoUnsizeLength(dereferences, len),
185 ty::ty_err => return None,
192 impl<'a,'tcx> ProbeContext<'a,'tcx> {
193 fn new(fcx: &'a FnCtxt<'a,'tcx>,
195 method_name: ast::Name,
196 steps: Vec<CandidateStep<'tcx>>,
197 opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>)
198 -> ProbeContext<'a,'tcx>
203 method_name: method_name,
204 inherent_candidates: Vec::new(),
205 extension_candidates: Vec::new(),
206 impl_dups: HashSet::new(),
207 steps: Rc::new(steps),
208 opt_simplified_steps: opt_simplified_steps,
209 static_candidates: Vec::new(),
213 fn tcx(&self) -> &'a ty::ctxt<'tcx> {
217 fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
221 ///////////////////////////////////////////////////////////////////////////
222 // CANDIDATE ASSEMBLY
224 fn assemble_inherent_candidates(&mut self) {
225 let steps = self.steps.clone();
226 for step in steps.iter() {
227 self.assemble_probe(step.self_ty);
231 fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
232 debug!("assemble_probe: self_ty={}",
233 self_ty.repr(self.tcx()));
236 ty::ty_trait(box ref data) => {
237 self.assemble_inherent_candidates_from_object(self_ty, data);
238 self.assemble_inherent_impl_candidates_for_type(data.principal_def_id());
240 ty::ty_enum(did, _) |
241 ty::ty_struct(did, _) |
242 ty::ty_unboxed_closure(did, _, _) => {
243 self.assemble_inherent_impl_candidates_for_type(did);
246 self.assemble_inherent_candidates_from_param(self_ty, p);
253 fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) {
254 // Read the inherent implementation candidates for this type from the
255 // metadata if necessary.
256 ty::populate_implementations_for_type_if_necessary(self.tcx(), def_id);
258 for impl_infos in self.tcx().inherent_impls.borrow().get(&def_id).iter() {
259 for &impl_def_id in impl_infos.iter() {
260 self.assemble_inherent_impl_probe(impl_def_id);
265 fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) {
266 if !self.impl_dups.insert(impl_def_id) {
267 return; // already visited
270 debug!("assemble_inherent_impl_probe {}", impl_def_id);
272 let method = match impl_method(self.tcx(), impl_def_id, self.method_name) {
274 None => { return; } // No method with correct name on this impl
277 if !self.has_applicable_self(&*method) {
278 // No receiver declared. Not a candidate.
279 return self.record_static_candidate(ImplSource(impl_def_id));
282 let impl_substs = self.impl_substs(impl_def_id);
284 // Determine the receiver type that the method itself expects.
286 self.xform_self_ty(&method, &impl_substs);
288 self.inherent_candidates.push(Candidate {
289 xform_self_ty: xform_self_ty,
291 kind: InherentImplCandidate(impl_def_id, impl_substs)
295 fn assemble_inherent_candidates_from_object(&mut self,
297 data: &ty::TyTrait<'tcx>) {
298 debug!("assemble_inherent_candidates_from_object(self_ty={})",
299 self_ty.repr(self.tcx()));
301 let tcx = self.tcx();
303 // It is illegal to invoke a method on a trait instance that
304 // refers to the `Self` type. An error will be reported by
305 // `enforce_object_limitations()` if the method refers to the
306 // `Self` type anywhere other than the receiver. Here, we use
307 // a substitution that replaces `Self` with the object type
308 // itself. Hence, a `&self` method will wind up with an
309 // argument type like `&Trait`.
310 let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
311 self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
313 traits::get_vtable_index_of_object_method(tcx,
315 new_trait_ref.def_id(),
318 let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs());
320 this.inherent_candidates.push(Candidate {
321 xform_self_ty: xform_self_ty,
323 kind: ObjectCandidate(new_trait_ref.def_id(), method_num, vtable_index)
328 fn assemble_inherent_candidates_from_param(&mut self,
330 param_ty: ty::ParamTy) {
331 // FIXME -- Do we want to commit to this behavior for param bounds?
334 self.fcx.inh.param_env.caller_bounds.predicates
336 .filter_map(|predicate| {
338 ty::Predicate::Trait(ref trait_predicate) => {
339 match trait_predicate.0.trait_ref.self_ty().sty {
340 ty::ty_param(ref p) if *p == param_ty => {
341 Some(trait_predicate.to_poly_trait_ref())
346 ty::Predicate::Equate(..) |
347 ty::Predicate::Projection(..) |
348 ty::Predicate::RegionOutlives(..) |
349 ty::Predicate::TypeOutlives(..) => {
356 self.elaborate_bounds(bounds.as_slice(), true, |this, trait_ref, m, method_num| {
358 this.xform_self_ty(&m, trait_ref.substs());
360 debug!("found match: trait_ref={} substs={} m={}",
361 trait_ref.repr(this.tcx()),
362 trait_ref.substs().repr(this.tcx()),
364 assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(),
365 trait_ref.substs().types.get_slice(subst::TypeSpace).len());
366 assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(),
367 trait_ref.substs().regions().get_slice(subst::TypeSpace).len());
368 assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(),
369 trait_ref.substs().types.get_slice(subst::SelfSpace).len());
370 assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(),
371 trait_ref.substs().regions().get_slice(subst::SelfSpace).len());
373 // Because this trait derives from a where-clause, it
374 // should not contain any inference variables or other
375 // artifacts. This means it is safe to put into the
376 // `WhereClauseCandidate` and (eventually) into the
377 // `WhereClausePick`.
378 assert!(trait_ref.substs().types.iter().all(|&t| !ty::type_needs_infer(t)));
380 this.inherent_candidates.push(Candidate {
381 xform_self_ty: xform_self_ty,
383 kind: WhereClauseCandidate(trait_ref, method_num)
388 // Do a search through a list of bounds, using a callback to actually
389 // create the candidates.
392 bounds: &[ty::PolyTraitRef<'tcx>],
393 num_includes_types: bool,
394 mk_cand: for<'b> |this: &mut ProbeContext<'b, 'tcx>,
395 tr: ty::PolyTraitRef<'tcx>,
396 m: Rc<ty::Method<'tcx>>,
399 debug!("elaborate_bounds(bounds={})", bounds.repr(self.tcx()));
401 let tcx = self.tcx();
402 let mut cache = HashSet::new();
403 for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
404 // Already visited this trait, skip it.
405 if !cache.insert(bound_trait_ref.def_id()) {
409 let (pos, method) = match trait_method(tcx,
410 bound_trait_ref.def_id(),
412 num_includes_types) {
414 None => { continue; }
417 if !self.has_applicable_self(&*method) {
418 self.record_static_candidate(TraitSource(bound_trait_ref.def_id()));
420 mk_cand(self, bound_trait_ref, method, pos);
425 fn assemble_extension_candidates_for_traits_in_scope(&mut self,
426 expr_id: ast::NodeId)
428 let mut duplicates = HashSet::new();
429 let opt_applicable_traits = self.fcx.ccx.trait_map.get(&expr_id);
430 for applicable_traits in opt_applicable_traits.into_iter() {
431 for &trait_did in applicable_traits.iter() {
432 if duplicates.insert(trait_did) {
433 self.assemble_extension_candidates_for_trait(trait_did);
439 fn assemble_extension_candidates_for_trait(&mut self,
440 trait_def_id: ast::DefId) {
441 debug!("assemble_extension_candidates_for_trait: trait_def_id={}",
442 trait_def_id.repr(self.tcx()));
444 // Check whether `trait_def_id` defines a method with suitable name:
446 ty::trait_items(self.tcx(), trait_def_id);
449 .position(|item| item.name() == self.method_name);
450 let matching_index = match matching_index {
454 let method = match (&*trait_items)[matching_index].as_opt_method() {
459 // Check whether `trait_def_id` defines a method with suitable name:
460 if !self.has_applicable_self(&*method) {
461 debug!("method has inapplicable self");
462 return self.record_static_candidate(TraitSource(trait_def_id));
465 self.assemble_extension_candidates_for_trait_impls(trait_def_id,
469 self.assemble_unboxed_closure_candidates(trait_def_id,
474 fn assemble_extension_candidates_for_trait_impls(&mut self,
475 trait_def_id: ast::DefId,
476 method: Rc<ty::Method<'tcx>>,
479 ty::populate_implementations_for_trait_if_necessary(self.tcx(),
482 let trait_impls = self.tcx().trait_impls.borrow();
483 let impl_def_ids = match trait_impls.get(&trait_def_id) {
485 Some(impls) => impls,
488 for &impl_def_id in impl_def_ids.borrow().iter() {
489 debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={} impl_def_id={}",
490 trait_def_id.repr(self.tcx()),
491 impl_def_id.repr(self.tcx()));
493 if !self.impl_can_possibly_match(impl_def_id) {
497 let impl_substs = self.impl_substs(impl_def_id);
499 debug!("impl_substs={}", impl_substs.repr(self.tcx()));
502 ty::impl_trait_ref(self.tcx(), impl_def_id)
503 .unwrap() // we know this is a trait impl
504 .subst(self.tcx(), &impl_substs);
506 debug!("impl_trait_ref={}", impl_trait_ref.repr(self.tcx()));
508 // Determine the receiver type that the method itself expects.
510 self.xform_self_ty(&method, impl_trait_ref.substs);
512 debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
514 self.extension_candidates.push(Candidate {
515 xform_self_ty: xform_self_ty,
516 method_ty: method.clone(),
517 kind: ExtensionImplCandidate(impl_def_id, impl_trait_ref, impl_substs, method_index)
522 fn impl_can_possibly_match(&self, impl_def_id: ast::DefId) -> bool {
523 let simplified_steps = match self.opt_simplified_steps {
524 Some(ref simplified_steps) => simplified_steps,
525 None => { return true; }
528 let impl_type = ty::lookup_item_type(self.tcx(), impl_def_id);
529 let impl_simplified_type =
530 match fast_reject::simplify_type(self.tcx(), impl_type.ty, false) {
531 Some(simplified_type) => simplified_type,
532 None => { return true; }
535 simplified_steps.contains(&impl_simplified_type)
538 fn assemble_unboxed_closure_candidates(&mut self,
539 trait_def_id: ast::DefId,
540 method_ty: Rc<ty::Method<'tcx>>,
543 // Check if this is one of the Fn,FnMut,FnOnce traits.
544 let tcx = self.tcx();
545 let kind = if Some(trait_def_id) == tcx.lang_items.fn_trait() {
546 ty::FnUnboxedClosureKind
547 } else if Some(trait_def_id) == tcx.lang_items.fn_mut_trait() {
548 ty::FnMutUnboxedClosureKind
549 } else if Some(trait_def_id) == tcx.lang_items.fn_once_trait() {
550 ty::FnOnceUnboxedClosureKind
555 // Check if there is an unboxed-closure self-type in the list of receivers.
556 // If so, add "synthetic impls".
557 let steps = self.steps.clone();
558 for step in steps.iter() {
559 let (closure_def_id, _, _) = match step.self_ty.sty {
560 ty::ty_unboxed_closure(a, b, ref c) => (a, b, c),
564 let unboxed_closures = self.fcx.inh.unboxed_closures.borrow();
565 let closure_data = match unboxed_closures.get(&closure_def_id) {
568 self.tcx().sess.span_bug(
570 format!("No entry for unboxed closure: {}",
571 closure_def_id.repr(self.tcx()))[]);
575 // this closure doesn't implement the right kind of `Fn` trait
576 if closure_data.kind != kind {
580 // create some substitutions for the argument/return type;
581 // for the purposes of our method lookup, we only take
582 // receiver type into account, so we can just substitute
583 // fresh types here to use during substitution and subtyping.
584 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
585 let substs = self.infcx().fresh_substs_for_trait(self.span,
589 let xform_self_ty = self.xform_self_ty(&method_ty, &substs);
590 self.inherent_candidates.push(Candidate {
591 xform_self_ty: xform_self_ty,
592 method_ty: method_ty.clone(),
593 kind: UnboxedClosureCandidate(trait_def_id, method_index)
598 ///////////////////////////////////////////////////////////////////////////
601 fn pick(mut self) -> PickResult<'tcx> {
602 let steps = self.steps.clone();
604 for step in steps.iter() {
605 match self.pick_step(step) {
613 Err(NoMatch(self.static_candidates))
616 fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
617 debug!("pick_step: step={}", step.repr(self.tcx()));
619 if ty::type_is_error(step.self_ty) {
623 match self.pick_by_value_method(step) {
624 Some(result) => return Some(result),
628 self.pick_autorefd_method(step)
631 fn pick_by_value_method(&mut self,
632 step: &CandidateStep<'tcx>)
633 -> Option<PickResult<'tcx>>
636 * For each type `T` in the step list, this attempts to find a
637 * method where the (transformed) self type is exactly `T`. We
638 * do however do one transformation on the adjustment: if we
639 * are passing a region pointer in, we will potentially
640 * *reborrow* it to a shorter lifetime. This allows us to
641 * transparently pass `&mut` pointers, in particular, without
642 * consuming them for their entire lifetime.
645 let adjustment = match step.adjustment {
646 AutoDeref(d) => consider_reborrow(step.self_ty, d),
647 AutoUnsizeLength(..) | AutoRef(..) => step.adjustment.clone(),
650 return self.pick_method(step.self_ty).map(|r| self.adjust(r, adjustment.clone()));
652 fn consider_reborrow(ty: Ty, d: uint) -> PickAdjustment {
653 // Insert a `&*` or `&mut *` if this is a reference type:
655 ty::ty_rptr(_, ref mt) => AutoRef(mt.mutbl, box AutoDeref(d+1)),
661 fn pick_autorefd_method(&mut self,
662 step: &CandidateStep<'tcx>)
663 -> Option<PickResult<'tcx>>
665 let tcx = self.tcx();
666 self.search_mutabilities(
667 |m| AutoRef(m, box step.adjustment.clone()),
668 |m,r| ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty:step.self_ty, mutbl:m}))
671 fn search_mutabilities<F, G>(&mut self,
672 mut mk_adjustment: F,
673 mut mk_autoref_ty: G)
674 -> Option<PickResult<'tcx>> where
675 F: FnMut(ast::Mutability) -> PickAdjustment,
676 G: FnMut(ast::Mutability, ty::Region) -> Ty<'tcx>,
678 // In general, during probing we erase regions. See
679 // `impl_self_ty()` for an explanation.
680 let region = ty::ReStatic;
682 // Search through mutabilities in order to find one where pick works:
683 [ast::MutImmutable, ast::MutMutable]
686 let autoref_ty = mk_autoref_ty(m, region);
687 self.pick_method(autoref_ty)
688 .map(|r| self.adjust(r, mk_adjustment(m)))
695 result: PickResult<'tcx>,
696 adjustment: PickAdjustment)
697 -> PickResult<'tcx> {
701 pick.adjustment = adjustment;
707 fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
708 debug!("pick_method(self_ty={})", self.infcx().ty_to_string(self_ty));
710 debug!("searching inherent candidates");
711 match self.consider_candidates(self_ty, self.inherent_candidates[]) {
718 debug!("searching extension candidates");
719 self.consider_candidates(self_ty, self.extension_candidates[])
722 fn consider_candidates(&self,
724 probes: &[Candidate<'tcx>])
725 -> Option<PickResult<'tcx>> {
726 let mut applicable_candidates: Vec<_> =
728 .filter(|&probe| self.consider_probe(self_ty, probe))
731 debug!("applicable_candidates: {}", applicable_candidates.repr(self.tcx()));
733 if applicable_candidates.len() > 1 {
734 match self.collapse_candidates_to_trait_pick(applicable_candidates[]) {
735 Some(pick) => { return Some(Ok(pick)); }
740 if applicable_candidates.len() > 1 {
741 let sources = probes.iter().map(|p| p.to_source()).collect();
742 return Some(Err(Ambiguity(sources)));
745 applicable_candidates.pop().map(|probe| {
746 let pick = probe.to_unadjusted_pick();
751 fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>) -> bool {
752 debug!("consider_probe: self_ty={} probe={}",
753 self_ty.repr(self.tcx()),
754 probe.repr(self.tcx()));
756 self.infcx().probe(|_| {
757 // First check that the self type can be related.
758 match self.make_sub_ty(self_ty, probe.xform_self_ty) {
761 debug!("--> cannot relate self-types");
766 // If so, impls may carry other conditions (e.g., where
767 // clauses) that must be considered. Make sure that those
768 // match as well (or at least may match, sometimes we
769 // don't have enough information to fully evaluate).
771 InherentImplCandidate(impl_def_id, ref substs) |
772 ExtensionImplCandidate(impl_def_id, _, ref substs, _) => {
773 // Check whether the impl imposes obligations we have to worry about.
774 let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
775 let impl_bounds = impl_generics.to_bounds(self.tcx(), substs);
776 // FIXME(#20378) assoc type normalization here?
778 // Erase any late-bound regions bound in the impl
779 // which appear in the bounds.
780 let impl_bounds = self.erase_late_bound_regions(&ty::Binder(impl_bounds));
782 // Convert the bounds into obligations.
784 traits::predicates_for_generics(
786 traits::ObligationCause::misc(self.span, self.fcx.body_id),
788 debug!("impl_obligations={}", obligations.repr(self.tcx()));
790 // Evaluate those obligations to see if they might possibly hold.
791 let mut selcx = traits::SelectionContext::new(self.infcx(), self.fcx);
792 obligations.all(|o| selcx.evaluate_obligation(o))
795 ObjectCandidate(..) |
796 UnboxedClosureCandidate(..) |
797 WhereClauseCandidate(..) => {
798 // These have no additional conditions to check.
805 /// Sometimes we get in a situation where we have multiple probes that are all impls of the
806 /// same trait, but we don't know which impl to use. In this case, since in all cases the
807 /// external interface of the method can be determined from the trait, it's ok not to decide.
808 /// We can basically just collapse all of the probes for various impls into one where-clause
809 /// probe. This will result in a pending obligation so when more type-info is available we can
810 /// make the final decision.
812 /// Example (`src/test/run-pass/method-two-trait-defer-resolution-1.rs`):
815 /// trait Foo { ... }
816 /// impl Foo for Vec<int> { ... }
817 /// impl Foo for Vec<uint> { ... }
820 /// Now imagine the receiver is `Vec<_>`. It doesn't really matter at this time which impl we
821 /// use, so it's ok to just commit to "using the method from the trait Foo".
822 fn collapse_candidates_to_trait_pick(&self,
823 probes: &[&Candidate<'tcx>])
824 -> Option<Pick<'tcx>> {
825 // Do all probes correspond to the same trait?
826 let trait_data = match probes[0].to_trait_data() {
830 if probes[1..].iter().any(|p| p.to_trait_data() != Some(trait_data)) {
834 // If so, just use this trait and call it a day.
835 let (trait_def_id, method_num) = trait_data;
836 let method_ty = probes[0].method_ty.clone();
838 method_ty: method_ty,
839 adjustment: AutoDeref(0),
840 kind: TraitPick(trait_def_id, method_num)
844 ///////////////////////////////////////////////////////////////////////////
847 fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::ures<'tcx> {
848 self.infcx().sub_types(false, infer::Misc(DUMMY_SP), sub, sup)
851 fn has_applicable_self(&self, method: &ty::Method) -> bool {
852 // "fast track" -- check for usage of sugar
853 match method.explicit_self {
854 ty::StaticExplicitSelfCategory => {
857 ty::ByValueExplicitSelfCategory |
858 ty::ByReferenceExplicitSelfCategory(..) |
859 ty::ByBoxExplicitSelfCategory => {
864 // FIXME -- check for types that deref to `Self`,
865 // like `Rc<Self>` and so on.
867 // Note also that the current code will break if this type
868 // includes any of the type parameters defined on the method
869 // -- but this could be overcome.
873 fn record_static_candidate(&mut self, source: CandidateSource) {
874 self.static_candidates.push(source);
877 fn xform_self_ty(&self,
878 method: &Rc<ty::Method<'tcx>>,
879 substs: &subst::Substs<'tcx>)
882 debug!("xform_self_ty(self_ty={}, substs={})",
883 method.fty.sig.0.inputs[0].repr(self.tcx()),
884 substs.repr(self.tcx()));
886 // It is possible for type parameters or early-bound lifetimes
887 // to appear in the signature of `self`. The substitutions we
888 // are given do not include type/lifetime parameters for the
889 // method yet. So create fresh variables here for those too,
891 assert_eq!(substs.types.len(subst::FnSpace), 0);
892 assert_eq!(substs.regions().len(subst::FnSpace), 0);
893 let mut substs = substs;
896 !method.generics.types.is_empty_in(subst::FnSpace) ||
897 !method.generics.regions.is_empty_in(subst::FnSpace)
900 self.infcx().next_ty_vars(
901 method.generics.types.len(subst::FnSpace));
903 // In general, during probe we erase regions. See
904 // `impl_self_ty()` for an explanation.
906 method.generics.regions.get_slice(subst::FnSpace)
908 .map(|_| ty::ReStatic)
911 placeholder = (*substs).clone().with_method(method_types, method_regions);
912 substs = &placeholder;
915 // Replace early-bound regions and types.
916 let xform_self_ty = method.fty.sig.0.inputs[0].subst(self.tcx(), substs);
918 // Replace late-bound regions bound in the impl or
919 // where-clause (2 levels of binding) and method (1 level of binding).
920 self.erase_late_bound_regions(
921 &self.erase_late_bound_regions(
922 &ty::Binder(ty::Binder(xform_self_ty))))
925 fn impl_substs(&self,
926 impl_def_id: ast::DefId)
927 -> subst::Substs<'tcx>
929 let impl_pty = ty::lookup_item_type(self.tcx(), impl_def_id);
932 impl_pty.generics.types.map(
933 |_| self.infcx().next_ty_var());
935 let region_placeholders =
936 impl_pty.generics.regions.map(
937 |_| ty::ReStatic); // see erase_late_bound_regions() for an expl of why 'static
939 subst::Substs::new(type_vars, region_placeholders)
942 /// Replace late-bound-regions bound by `value` with `'static` using
943 /// `ty::erase_late_bound_regions`.
945 /// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of
946 /// method matching. It is reasonable during the probe phase because we don't consider region
947 /// relationships at all. Therefore, we can just replace all the region variables with 'static
948 /// rather than creating fresh region variables. This is nice for two reasons:
950 /// 1. Because the numbers of the region variables would otherwise be fairly unique to this
951 /// particular method call, it winds up creating fewer types overall, which helps for memory
952 /// usage. (Admittedly, this is a rather small effect, though measureable.)
954 /// 2. It makes it easier to deal with higher-ranked trait bounds, because we can replace any
955 /// late-bound regions with 'static. Otherwise, if we were going to replace late-bound
956 /// regions with actual region variables as is proper, we'd have to ensure that the same
957 /// region got replaced with the same variable, which requires a bit more coordination
958 /// and/or tracking the substitution and
960 fn erase_late_bound_regions<T>(&self, value: &ty::Binder<T>) -> T
961 where T : TypeFoldable<'tcx> + Repr<'tcx>
963 ty::erase_late_bound_regions(self.tcx(), value)
967 fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
968 impl_def_id: ast::DefId,
969 method_name: ast::Name)
970 -> Option<Rc<ty::Method<'tcx>>>
972 let impl_items = tcx.impl_items.borrow();
973 let impl_items = impl_items.get(&impl_def_id).unwrap();
976 .map(|&did| ty::impl_or_trait_item(tcx, did.def_id()))
977 .find(|m| m.name() == method_name)
978 .and_then(|item| item.as_opt_method())
981 /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
982 /// index (or `None`, if no such method).
983 fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
984 trait_def_id: ast::DefId,
985 method_name: ast::Name,
986 num_includes_types: bool)
987 -> Option<(uint, Rc<ty::Method<'tcx>>)>
989 let trait_items = ty::trait_items(tcx, trait_def_id);
990 debug!("trait_method; items: {}", trait_items);
994 num_includes_types || match *item {
995 &ty::MethodTraitItem(_) => true,
996 &ty::TypeTraitItem(_) => false
999 .find(|&(_, ref item)| item.name() == method_name)
1000 .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
1003 impl<'tcx> Candidate<'tcx> {
1004 fn to_unadjusted_pick(&self) -> Pick<'tcx> {
1006 method_ty: self.method_ty.clone(),
1007 adjustment: AutoDeref(0),
1008 kind: match self.kind {
1009 InherentImplCandidate(def_id, _) => {
1010 InherentImplPick(def_id)
1012 ObjectCandidate(def_id, method_num, real_index) => {
1013 ObjectPick(def_id, method_num, real_index)
1015 ExtensionImplCandidate(def_id, _, _, index) => {
1016 ExtensionImplPick(def_id, index)
1018 UnboxedClosureCandidate(trait_def_id, index) => {
1019 TraitPick(trait_def_id, index)
1021 WhereClauseCandidate(ref trait_ref, index) => {
1022 // Only trait derived from where-clauses should
1023 // appear here, so they should not contain any
1024 // inference variables or other artifacts. This
1025 // means they are safe to put into the
1026 // `WhereClausePick`.
1027 assert!(trait_ref.substs().types.iter().all(|&t| !ty::type_needs_infer(t)));
1029 WhereClausePick((*trait_ref).clone(), index)
1035 fn to_source(&self) -> CandidateSource {
1037 InherentImplCandidate(def_id, _) => ImplSource(def_id),
1038 ObjectCandidate(def_id, _, _) => TraitSource(def_id),
1039 ExtensionImplCandidate(def_id, _, _, _) => ImplSource(def_id),
1040 UnboxedClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id),
1041 WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()),
1045 fn to_trait_data(&self) -> Option<(ast::DefId,MethodIndex)> {
1047 InherentImplCandidate(..) |
1048 ObjectCandidate(..) => {
1051 UnboxedClosureCandidate(trait_def_id, method_num) => {
1052 Some((trait_def_id, method_num))
1054 ExtensionImplCandidate(_, ref trait_ref, _, method_num) => {
1055 Some((trait_ref.def_id, method_num))
1057 WhereClauseCandidate(ref trait_ref, method_num) => {
1058 Some((trait_ref.def_id(), method_num))
1064 impl<'tcx> Repr<'tcx> for Candidate<'tcx> {
1065 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
1066 format!("Candidate(xform_self_ty={}, kind={})",
1067 self.xform_self_ty.repr(tcx),
1068 self.kind.repr(tcx))
1072 impl<'tcx> Repr<'tcx> for CandidateKind<'tcx> {
1073 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
1075 InherentImplCandidate(ref a, ref b) =>
1076 format!("InherentImplCandidate({},{})", a.repr(tcx), b.repr(tcx)),
1077 ObjectCandidate(a, b, c) =>
1078 format!("ObjectCandidate({},{},{})", a.repr(tcx), b, c),
1079 ExtensionImplCandidate(ref a, ref b, ref c, ref d) =>
1080 format!("ExtensionImplCandidate({},{},{},{})", a.repr(tcx), b.repr(tcx),
1082 UnboxedClosureCandidate(ref a, ref b) =>
1083 format!("UnboxedClosureCandidate({},{})", a.repr(tcx), b),
1084 WhereClauseCandidate(ref a, ref b) =>
1085 format!("WhereClauseCandidate({},{})", a.repr(tcx), b),
1090 impl<'tcx> Repr<'tcx> for CandidateStep<'tcx> {
1091 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
1092 format!("CandidateStep({},{})",
1093 self.self_ty.repr(tcx),
1098 impl<'tcx> Repr<'tcx> for PickAdjustment {
1099 fn repr(&self, _tcx: &ty::ctxt) -> String {
1104 impl<'tcx> Repr<'tcx> for PickKind<'tcx> {
1105 fn repr(&self, _tcx: &ty::ctxt) -> String {
1110 impl<'tcx> Repr<'tcx> for Pick<'tcx> {
1111 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
1112 format!("Pick(method_ty={}, adjustment={}, kind={})",
1113 self.method_ty.repr(tcx),