]>
Commit | Line | Data |
---|---|---|
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 | ||
c34b1796 | 11 | use super::MethodError; |
62682a34 | 12 | use super::NoMatchData; |
62682a34 | 13 | use super::{CandidateSource, ImplSource, TraitSource}; |
85aaf69f | 14 | use super::suggest; |
1a4d82fc | 15 | |
c30ab7b3 | 16 | use check::FnCtxt; |
54a0048b SL |
17 | use hir::def_id::DefId; |
18 | use hir::def::Def; | |
9e0c209e | 19 | use rustc::ty::subst::{Subst, Substs}; |
476ff2be | 20 | use rustc::traits::{self, ObligationCause}; |
3157f602 | 21 | use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; |
476ff2be SL |
22 | use rustc::infer::type_variable::TypeVariableOrigin; |
23 | use rustc::util::nodemap::FxHashSet; | |
32a655c1 | 24 | use rustc::infer::{self, InferOk}; |
1a4d82fc | 25 | use syntax::ast; |
476ff2be | 26 | use syntax_pos::Span; |
54a0048b | 27 | use rustc::hir; |
85aaf69f | 28 | use std::mem; |
a7813a04 | 29 | use std::ops::Deref; |
1a4d82fc | 30 | use std::rc::Rc; |
1a4d82fc JJ |
31 | |
32 | use self::CandidateKind::*; | |
1a4d82fc JJ |
33 | pub use self::PickKind::*; |
34 | ||
32a655c1 SL |
35 | pub enum LookingFor<'tcx> { |
36 | /// looking for methods with the given name; this is the normal case | |
37 | MethodName(ast::Name), | |
38 | ||
39 | /// looking for methods that return a given type; this is used to | |
40 | /// assemble suggestions | |
41 | ReturnType(Ty<'tcx>), | |
42 | } | |
43 | ||
44 | /// Boolean flag used to indicate if this search is for a suggestion | |
45 | /// or not. If true, we can allow ambiguity and so forth. | |
46 | pub struct IsSuggestion(pub bool); | |
47 | ||
c30ab7b3 | 48 | struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { |
a7813a04 | 49 | fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, |
1a4d82fc | 50 | span: Span, |
c34b1796 | 51 | mode: Mode, |
32a655c1 | 52 | looking_for: LookingFor<'tcx>, |
1a4d82fc | 53 | steps: Rc<Vec<CandidateStep<'tcx>>>, |
e9174d1e | 54 | opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>, |
1a4d82fc JJ |
55 | inherent_candidates: Vec<Candidate<'tcx>>, |
56 | extension_candidates: Vec<Candidate<'tcx>>, | |
476ff2be | 57 | impl_dups: FxHashSet<DefId>, |
62682a34 SL |
58 | |
59 | /// Collects near misses when the candidate functions are missing a `self` keyword and is only | |
60 | /// used for error reporting | |
1a4d82fc | 61 | static_candidates: Vec<CandidateSource>, |
62682a34 | 62 | |
54a0048b SL |
63 | /// Some(candidate) if there is a private candidate |
64 | private_candidate: Option<Def>, | |
65 | ||
62682a34 SL |
66 | /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used |
67 | /// for error reporting | |
c30ab7b3 | 68 | unsatisfied_predicates: Vec<TraitRef<'tcx>>, |
1a4d82fc JJ |
69 | } |
70 | ||
a7813a04 XL |
71 | impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> { |
72 | type Target = FnCtxt<'a, 'gcx, 'tcx>; | |
73 | fn deref(&self) -> &Self::Target { | |
74 | &self.fcx | |
75 | } | |
76 | } | |
77 | ||
62682a34 | 78 | #[derive(Debug)] |
1a4d82fc JJ |
79 | struct CandidateStep<'tcx> { |
80 | self_ty: Ty<'tcx>, | |
9346a6ac | 81 | autoderefs: usize, |
c30ab7b3 | 82 | unsize: bool, |
1a4d82fc JJ |
83 | } |
84 | ||
62682a34 | 85 | #[derive(Debug)] |
1a4d82fc JJ |
86 | struct Candidate<'tcx> { |
87 | xform_self_ty: Ty<'tcx>, | |
476ff2be | 88 | item: ty::AssociatedItem, |
1a4d82fc | 89 | kind: CandidateKind<'tcx>, |
a7813a04 | 90 | import_id: Option<ast::NodeId>, |
1a4d82fc JJ |
91 | } |
92 | ||
62682a34 | 93 | #[derive(Debug)] |
1a4d82fc | 94 | enum CandidateKind<'tcx> { |
9e0c209e | 95 | InherentImplCandidate(&'tcx Substs<'tcx>, |
c30ab7b3 SL |
96 | // Normalize obligations |
97 | Vec<traits::PredicateObligation<'tcx>>), | |
98 | ExtensionImplCandidate(// Impl | |
99 | DefId, | |
100 | &'tcx Substs<'tcx>, | |
101 | // Normalize obligations | |
102 | Vec<traits::PredicateObligation<'tcx>>), | |
c1a9b12d SL |
103 | ObjectCandidate, |
104 | TraitCandidate, | |
c30ab7b3 SL |
105 | WhereClauseCandidate(// Trait |
106 | ty::PolyTraitRef<'tcx>), | |
1a4d82fc JJ |
107 | } |
108 | ||
62682a34 | 109 | #[derive(Debug)] |
1a4d82fc | 110 | pub struct Pick<'tcx> { |
476ff2be | 111 | pub item: ty::AssociatedItem, |
1a4d82fc | 112 | pub kind: PickKind<'tcx>, |
a7813a04 | 113 | pub import_id: Option<ast::NodeId>, |
9346a6ac AL |
114 | |
115 | // Indicates that the source expression should be autoderef'd N times | |
116 | // | |
117 | // A = expr | *expr | **expr | ... | |
118 | pub autoderefs: usize, | |
119 | ||
120 | // Indicates that an autoref is applied after the optional autoderefs | |
121 | // | |
122 | // B = A | &A | &mut A | |
e9174d1e | 123 | pub autoref: Option<hir::Mutability>, |
9346a6ac AL |
124 | |
125 | // Indicates that the source expression should be "unsized" to a | |
126 | // target type. This should probably eventually go away in favor | |
127 | // of just coercing method receivers. | |
128 | // | |
129 | // C = B | unsize(B) | |
130 | pub unsize: Option<Ty<'tcx>>, | |
1a4d82fc JJ |
131 | } |
132 | ||
85aaf69f | 133 | #[derive(Clone,Debug)] |
1a4d82fc | 134 | pub enum PickKind<'tcx> { |
c1a9b12d | 135 | InherentImplPick, |
c30ab7b3 SL |
136 | ExtensionImplPick(// Impl |
137 | DefId), | |
c1a9b12d SL |
138 | ObjectPick, |
139 | TraitPick, | |
c30ab7b3 SL |
140 | WhereClausePick(// Trait |
141 | ty::PolyTraitRef<'tcx>), | |
1a4d82fc JJ |
142 | } |
143 | ||
62682a34 | 144 | pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>; |
1a4d82fc | 145 | |
d9579d0f | 146 | #[derive(PartialEq, Eq, Copy, Clone, Debug)] |
c34b1796 AL |
147 | pub enum Mode { |
148 | // An expression of the form `receiver.method_name(...)`. | |
149 | // Autoderefs are performed on `receiver`, lookup is done based on the | |
150 | // `self` argument of the method, and static methods aren't considered. | |
151 | MethodCall, | |
d9579d0f | 152 | // An expression of the form `Type::item` or `<T>::item`. |
c34b1796 AL |
153 | // No autoderefs are performed, lookup is done based on the type each |
154 | // implementation is for, and static methods are included. | |
c30ab7b3 | 155 | Path, |
c34b1796 AL |
156 | } |
157 | ||
a7813a04 | 158 | impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { |
32a655c1 SL |
159 | /// This is used to offer suggestions to users. It returns methods |
160 | /// that could have been called which have the desired return | |
161 | /// type. Some effort is made to rule out methods that, if called, | |
162 | /// would result in an error (basically, the same criteria we | |
163 | /// would use to decide if a method is a plausible fit for | |
164 | /// ambiguity purposes). | |
165 | pub fn probe_for_return_type(&self, | |
166 | span: Span, | |
167 | mode: Mode, | |
168 | return_type: Ty<'tcx>, | |
169 | self_ty: Ty<'tcx>, | |
170 | scope_expr_id: ast::NodeId) | |
171 | -> Vec<ty::AssociatedItem> { | |
172 | debug!("probe(self_ty={:?}, return_type={}, scope_expr_id={})", | |
173 | self_ty, | |
174 | return_type, | |
175 | scope_expr_id); | |
176 | let method_names = | |
177 | self.probe_op(span, mode, LookingFor::ReturnType(return_type), IsSuggestion(true), | |
178 | self_ty, scope_expr_id, | |
179 | |probe_cx| Ok(probe_cx.candidate_method_names())) | |
180 | .unwrap_or(vec![]); | |
181 | method_names | |
182 | .iter() | |
183 | .flat_map(|&method_name| { | |
184 | match self.probe_for_name(span, mode, method_name, IsSuggestion(true), self_ty, | |
185 | scope_expr_id) { | |
186 | Ok(pick) => Some(pick.item), | |
187 | Err(_) => None, | |
188 | } | |
189 | }) | |
190 | .collect() | |
191 | } | |
192 | ||
193 | pub fn probe_for_name(&self, | |
194 | span: Span, | |
195 | mode: Mode, | |
196 | item_name: ast::Name, | |
197 | is_suggestion: IsSuggestion, | |
198 | self_ty: Ty<'tcx>, | |
199 | scope_expr_id: ast::NodeId) | |
200 | -> PickResult<'tcx> { | |
a7813a04 XL |
201 | debug!("probe(self_ty={:?}, item_name={}, scope_expr_id={})", |
202 | self_ty, | |
203 | item_name, | |
204 | scope_expr_id); | |
32a655c1 SL |
205 | self.probe_op(span, |
206 | mode, | |
207 | LookingFor::MethodName(item_name), | |
208 | is_suggestion, | |
209 | self_ty, | |
210 | scope_expr_id, | |
211 | |probe_cx| probe_cx.pick()) | |
212 | } | |
a7813a04 | 213 | |
32a655c1 SL |
214 | fn probe_op<OP,R>(&'a self, |
215 | span: Span, | |
216 | mode: Mode, | |
217 | looking_for: LookingFor<'tcx>, | |
218 | is_suggestion: IsSuggestion, | |
219 | self_ty: Ty<'tcx>, | |
220 | scope_expr_id: ast::NodeId, | |
221 | op: OP) | |
222 | -> Result<R, MethodError<'tcx>> | |
223 | where OP: FnOnce(ProbeContext<'a, 'gcx, 'tcx>) -> Result<R, MethodError<'tcx>> | |
224 | { | |
a7813a04 XL |
225 | // FIXME(#18741) -- right now, creating the steps involves evaluating the |
226 | // `*` operator, which registers obligations that then escape into | |
227 | // the global fulfillment context and thus has global | |
228 | // side-effects. This is a bit of a pain to refactor. So just let | |
229 | // it ride, although it's really not great, and in fact could I | |
230 | // think cause spurious errors. Really though this part should | |
231 | // take place in the `self.probe` below. | |
232 | let steps = if mode == Mode::MethodCall { | |
32a655c1 | 233 | match self.create_steps(span, self_ty, is_suggestion) { |
a7813a04 | 234 | Some(steps) => steps, |
c30ab7b3 SL |
235 | None => { |
236 | return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(), | |
237 | Vec::new(), | |
238 | Vec::new(), | |
239 | mode))) | |
240 | } | |
a7813a04 | 241 | } |
1a4d82fc | 242 | } else { |
a7813a04 | 243 | vec![CandidateStep { |
c30ab7b3 SL |
244 | self_ty: self_ty, |
245 | autoderefs: 0, | |
246 | unsize: false, | |
247 | }] | |
1a4d82fc JJ |
248 | }; |
249 | ||
a7813a04 XL |
250 | // Create a list of simplified self types, if we can. |
251 | let mut simplified_steps = Vec::new(); | |
252 | for step in &steps { | |
253 | match ty::fast_reject::simplify_type(self.tcx, step.self_ty, true) { | |
c30ab7b3 SL |
254 | None => { |
255 | break; | |
256 | } | |
257 | Some(simplified_type) => { | |
258 | simplified_steps.push(simplified_type); | |
259 | } | |
a7813a04 XL |
260 | } |
261 | } | |
c30ab7b3 SL |
262 | let opt_simplified_steps = if simplified_steps.len() < steps.len() { |
263 | None // failed to convert at least one of the steps | |
264 | } else { | |
265 | Some(simplified_steps) | |
266 | }; | |
1a4d82fc | 267 | |
a7813a04 XL |
268 | debug!("ProbeContext: steps for self_ty={:?} are {:?}", |
269 | self_ty, | |
270 | steps); | |
271 | ||
272 | // this creates one big transaction so that all type variables etc | |
273 | // that we create during the probe process are removed later | |
274 | self.probe(|_| { | |
c30ab7b3 | 275 | let mut probe_cx = |
32a655c1 SL |
276 | ProbeContext::new(self, span, mode, looking_for, |
277 | steps, opt_simplified_steps); | |
a7813a04 XL |
278 | probe_cx.assemble_inherent_candidates(); |
279 | probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id)?; | |
32a655c1 | 280 | op(probe_cx) |
a7813a04 XL |
281 | }) |
282 | } | |
85aaf69f | 283 | |
32a655c1 SL |
284 | fn create_steps(&self, |
285 | span: Span, | |
286 | self_ty: Ty<'tcx>, | |
287 | is_suggestion: IsSuggestion) | |
288 | -> Option<Vec<CandidateStep<'tcx>>> { | |
3157f602 | 289 | // FIXME: we don't need to create the entire steps in one pass |
a7813a04 | 290 | |
3157f602 | 291 | let mut autoderef = self.autoderef(span, self_ty); |
c30ab7b3 SL |
292 | let mut steps: Vec<_> = autoderef.by_ref() |
293 | .map(|(ty, d)| { | |
294 | CandidateStep { | |
295 | self_ty: ty, | |
296 | autoderefs: d, | |
297 | unsize: false, | |
298 | } | |
299 | }) | |
300 | .collect(); | |
3157f602 | 301 | |
32a655c1 | 302 | let final_ty = autoderef.maybe_ambiguous_final_ty(); |
a7813a04 | 303 | match final_ty.sty { |
32a655c1 SL |
304 | ty::TyInfer(ty::TyVar(_)) => { |
305 | // Ended in an inference variable. If we are doing | |
306 | // a real method lookup, this is a hard error (it's an | |
307 | // ambiguity and we can't make progress). | |
308 | if !is_suggestion.0 { | |
309 | let t = self.structurally_resolved_type(span, final_ty); | |
310 | assert_eq!(t, self.tcx.types.err); | |
311 | return None | |
312 | } else { | |
313 | // If we're just looking for suggestions, | |
314 | // though, ambiguity is no big thing, we can | |
315 | // just ignore it. | |
316 | } | |
317 | } | |
a7813a04 | 318 | ty::TyArray(elem_ty, _) => { |
3157f602 XL |
319 | let dereferences = steps.len() - 1; |
320 | ||
a7813a04 XL |
321 | steps.push(CandidateStep { |
322 | self_ty: self.tcx.mk_slice(elem_ty), | |
323 | autoderefs: dereferences, | |
c30ab7b3 | 324 | unsize: true, |
a7813a04 XL |
325 | }); |
326 | } | |
327 | ty::TyError => return None, | |
328 | _ => (), | |
1a4d82fc | 329 | } |
1a4d82fc | 330 | |
3157f602 XL |
331 | debug!("create_steps: steps={:?}", steps); |
332 | ||
a7813a04 XL |
333 | Some(steps) |
334 | } | |
1a4d82fc JJ |
335 | } |
336 | ||
a7813a04 XL |
337 | impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { |
338 | fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, | |
1a4d82fc | 339 | span: Span, |
c34b1796 | 340 | mode: Mode, |
32a655c1 | 341 | looking_for: LookingFor<'tcx>, |
1a4d82fc | 342 | steps: Vec<CandidateStep<'tcx>>, |
e9174d1e | 343 | opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>) |
c30ab7b3 | 344 | -> ProbeContext<'a, 'gcx, 'tcx> { |
1a4d82fc JJ |
345 | ProbeContext { |
346 | fcx: fcx, | |
347 | span: span, | |
c34b1796 | 348 | mode: mode, |
32a655c1 | 349 | looking_for: looking_for, |
1a4d82fc JJ |
350 | inherent_candidates: Vec::new(), |
351 | extension_candidates: Vec::new(), | |
476ff2be | 352 | impl_dups: FxHashSet(), |
1a4d82fc JJ |
353 | steps: Rc::new(steps), |
354 | opt_simplified_steps: opt_simplified_steps, | |
355 | static_candidates: Vec::new(), | |
54a0048b | 356 | private_candidate: None, |
62682a34 | 357 | unsatisfied_predicates: Vec::new(), |
1a4d82fc JJ |
358 | } |
359 | } | |
360 | ||
85aaf69f SL |
361 | fn reset(&mut self) { |
362 | self.inherent_candidates.clear(); | |
363 | self.extension_candidates.clear(); | |
364 | self.impl_dups.clear(); | |
365 | self.static_candidates.clear(); | |
54a0048b | 366 | self.private_candidate = None; |
85aaf69f SL |
367 | } |
368 | ||
1a4d82fc JJ |
369 | /////////////////////////////////////////////////////////////////////////// |
370 | // CANDIDATE ASSEMBLY | |
371 | ||
7cac9316 XL |
372 | fn push_inherent_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem, |
373 | kind: CandidateKind<'tcx>, import_id: Option<ast::NodeId>) { | |
374 | let is_accessible = if let LookingFor::MethodName(name) = self.looking_for { | |
375 | let def_scope = self.tcx.adjust(name, item.container.id(), self.body_id).1; | |
376 | item.vis.is_accessible_from(def_scope, self.tcx) | |
377 | } else { | |
378 | true | |
379 | }; | |
380 | if is_accessible { | |
381 | self.inherent_candidates.push(Candidate { xform_self_ty, item, kind, import_id }); | |
382 | } else if self.private_candidate.is_none() { | |
383 | self.private_candidate = Some(item.def()); | |
384 | } | |
385 | } | |
386 | ||
387 | fn push_extension_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem, | |
388 | kind: CandidateKind<'tcx>, import_id: Option<ast::NodeId>) { | |
389 | let is_accessible = if let LookingFor::MethodName(name) = self.looking_for { | |
390 | let def_scope = self.tcx.adjust(name, item.container.id(), self.body_id).1; | |
391 | item.vis.is_accessible_from(def_scope, self.tcx) | |
392 | } else { | |
393 | true | |
394 | }; | |
395 | if is_accessible { | |
396 | self.extension_candidates.push(Candidate { xform_self_ty, item, kind, import_id }); | |
397 | } else if self.private_candidate.is_none() { | |
398 | self.private_candidate = Some(item.def()); | |
399 | } | |
400 | } | |
401 | ||
1a4d82fc JJ |
402 | fn assemble_inherent_candidates(&mut self) { |
403 | let steps = self.steps.clone(); | |
62682a34 | 404 | for step in steps.iter() { |
1a4d82fc JJ |
405 | self.assemble_probe(step.self_ty); |
406 | } | |
407 | } | |
408 | ||
409 | fn assemble_probe(&mut self, self_ty: Ty<'tcx>) { | |
c30ab7b3 | 410 | debug!("assemble_probe: self_ty={:?}", self_ty); |
1a4d82fc JJ |
411 | |
412 | match self_ty.sty { | |
476ff2be SL |
413 | ty::TyDynamic(ref data, ..) => { |
414 | if let Some(p) = data.principal() { | |
415 | self.assemble_inherent_candidates_from_object(self_ty, p); | |
416 | self.assemble_inherent_impl_candidates_for_type(p.def_id()); | |
417 | } | |
1a4d82fc | 418 | } |
9e0c209e | 419 | ty::TyAdt(def, _) => { |
e9174d1e | 420 | self.assemble_inherent_impl_candidates_for_type(def.did); |
1a4d82fc | 421 | } |
62682a34 | 422 | ty::TyParam(p) => { |
1a4d82fc JJ |
423 | self.assemble_inherent_candidates_from_param(self_ty, p); |
424 | } | |
62682a34 | 425 | ty::TyChar => { |
a7813a04 | 426 | let lang_def_id = self.tcx.lang_items.char_impl(); |
c34b1796 AL |
427 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
428 | } | |
62682a34 | 429 | ty::TyStr => { |
a7813a04 | 430 | let lang_def_id = self.tcx.lang_items.str_impl(); |
c34b1796 AL |
431 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
432 | } | |
62682a34 | 433 | ty::TySlice(_) => { |
a7813a04 | 434 | let lang_def_id = self.tcx.lang_items.slice_impl(); |
c34b1796 AL |
435 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
436 | } | |
e9174d1e | 437 | ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { |
a7813a04 | 438 | let lang_def_id = self.tcx.lang_items.const_ptr_impl(); |
c34b1796 AL |
439 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
440 | } | |
e9174d1e | 441 | ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { |
a7813a04 | 442 | let lang_def_id = self.tcx.lang_items.mut_ptr_impl(); |
c34b1796 AL |
443 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
444 | } | |
7453a54e | 445 | ty::TyInt(ast::IntTy::I8) => { |
a7813a04 | 446 | let lang_def_id = self.tcx.lang_items.i8_impl(); |
c34b1796 AL |
447 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
448 | } | |
7453a54e | 449 | ty::TyInt(ast::IntTy::I16) => { |
a7813a04 | 450 | let lang_def_id = self.tcx.lang_items.i16_impl(); |
c34b1796 AL |
451 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
452 | } | |
7453a54e | 453 | ty::TyInt(ast::IntTy::I32) => { |
a7813a04 | 454 | let lang_def_id = self.tcx.lang_items.i32_impl(); |
c34b1796 AL |
455 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
456 | } | |
7453a54e | 457 | ty::TyInt(ast::IntTy::I64) => { |
a7813a04 | 458 | let lang_def_id = self.tcx.lang_items.i64_impl(); |
c34b1796 AL |
459 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
460 | } | |
32a655c1 SL |
461 | ty::TyInt(ast::IntTy::I128) => { |
462 | let lang_def_id = self.tcx.lang_items.i128_impl(); | |
463 | self.assemble_inherent_impl_for_primitive(lang_def_id); | |
464 | } | |
7453a54e | 465 | ty::TyInt(ast::IntTy::Is) => { |
a7813a04 | 466 | let lang_def_id = self.tcx.lang_items.isize_impl(); |
c34b1796 AL |
467 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
468 | } | |
7453a54e | 469 | ty::TyUint(ast::UintTy::U8) => { |
a7813a04 | 470 | let lang_def_id = self.tcx.lang_items.u8_impl(); |
c34b1796 AL |
471 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
472 | } | |
7453a54e | 473 | ty::TyUint(ast::UintTy::U16) => { |
a7813a04 | 474 | let lang_def_id = self.tcx.lang_items.u16_impl(); |
c34b1796 AL |
475 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
476 | } | |
7453a54e | 477 | ty::TyUint(ast::UintTy::U32) => { |
a7813a04 | 478 | let lang_def_id = self.tcx.lang_items.u32_impl(); |
c34b1796 AL |
479 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
480 | } | |
7453a54e | 481 | ty::TyUint(ast::UintTy::U64) => { |
a7813a04 | 482 | let lang_def_id = self.tcx.lang_items.u64_impl(); |
c34b1796 AL |
483 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
484 | } | |
32a655c1 SL |
485 | ty::TyUint(ast::UintTy::U128) => { |
486 | let lang_def_id = self.tcx.lang_items.u128_impl(); | |
487 | self.assemble_inherent_impl_for_primitive(lang_def_id); | |
488 | } | |
7453a54e | 489 | ty::TyUint(ast::UintTy::Us) => { |
a7813a04 | 490 | let lang_def_id = self.tcx.lang_items.usize_impl(); |
c34b1796 AL |
491 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
492 | } | |
7453a54e | 493 | ty::TyFloat(ast::FloatTy::F32) => { |
a7813a04 | 494 | let lang_def_id = self.tcx.lang_items.f32_impl(); |
c34b1796 AL |
495 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
496 | } | |
7453a54e | 497 | ty::TyFloat(ast::FloatTy::F64) => { |
a7813a04 | 498 | let lang_def_id = self.tcx.lang_items.f64_impl(); |
c34b1796 AL |
499 | self.assemble_inherent_impl_for_primitive(lang_def_id); |
500 | } | |
c30ab7b3 | 501 | _ => {} |
1a4d82fc JJ |
502 | } |
503 | } | |
504 | ||
e9174d1e | 505 | fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<DefId>) { |
c34b1796 | 506 | if let Some(impl_def_id) = lang_def_id { |
c34b1796 AL |
507 | self.assemble_inherent_impl_probe(impl_def_id); |
508 | } | |
509 | } | |
510 | ||
e9174d1e | 511 | fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) { |
7cac9316 | 512 | let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id); |
cc61c64b XL |
513 | for &impl_def_id in impl_def_ids.iter() { |
514 | self.assemble_inherent_impl_probe(impl_def_id); | |
1a4d82fc JJ |
515 | } |
516 | } | |
517 | ||
e9174d1e | 518 | fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) { |
1a4d82fc JJ |
519 | if !self.impl_dups.insert(impl_def_id) { |
520 | return; // already visited | |
521 | } | |
522 | ||
523 | debug!("assemble_inherent_impl_probe {:?}", impl_def_id); | |
524 | ||
32a655c1 SL |
525 | for item in self.impl_or_trait_item(impl_def_id) { |
526 | if !self.has_applicable_self(&item) { | |
527 | // No receiver declared. Not a candidate. | |
528 | self.record_static_candidate(ImplSource(impl_def_id)); | |
529 | continue | |
530 | } | |
1a4d82fc | 531 | |
32a655c1 SL |
532 | let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); |
533 | let impl_ty = impl_ty.subst(self.tcx, impl_substs); | |
54a0048b | 534 | |
32a655c1 SL |
535 | // Determine the receiver type that the method itself expects. |
536 | let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs); | |
537 | ||
538 | // We can't use normalize_associated_types_in as it will pollute the | |
539 | // fcx's fulfillment context after this probe is over. | |
540 | let cause = traits::ObligationCause::misc(self.span, self.body_id); | |
541 | let mut selcx = &mut traits::SelectionContext::new(self.fcx); | |
542 | let traits::Normalized { value: xform_self_ty, obligations } = | |
7cac9316 | 543 | traits::normalize(selcx, self.param_env, cause, &xform_self_ty); |
32a655c1 SL |
544 | debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}", |
545 | xform_self_ty); | |
546 | ||
7cac9316 XL |
547 | self.push_inherent_candidate(xform_self_ty, item, |
548 | InherentImplCandidate(impl_substs, obligations), None); | |
32a655c1 | 549 | } |
1a4d82fc JJ |
550 | } |
551 | ||
552 | fn assemble_inherent_candidates_from_object(&mut self, | |
553 | self_ty: Ty<'tcx>, | |
9e0c209e | 554 | principal: ty::PolyExistentialTraitRef<'tcx>) { |
62682a34 SL |
555 | debug!("assemble_inherent_candidates_from_object(self_ty={:?})", |
556 | self_ty); | |
1a4d82fc | 557 | |
1a4d82fc JJ |
558 | // It is illegal to invoke a method on a trait instance that |
559 | // refers to the `Self` type. An error will be reported by | |
560 | // `enforce_object_limitations()` if the method refers to the | |
561 | // `Self` type anywhere other than the receiver. Here, we use | |
562 | // a substitution that replaces `Self` with the object type | |
563 | // itself. Hence, a `&self` method will wind up with an | |
564 | // argument type like `&Trait`. | |
9e0c209e | 565 | let trait_ref = principal.with_self_ty(self.tcx, self_ty); |
c1a9b12d | 566 | self.elaborate_bounds(&[trait_ref], |this, new_trait_ref, item| { |
1a4d82fc JJ |
567 | let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref); |
568 | ||
c30ab7b3 SL |
569 | let xform_self_ty = |
570 | this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs); | |
1a4d82fc | 571 | |
7cac9316 | 572 | this.push_inherent_candidate(xform_self_ty, item, ObjectCandidate, None); |
1a4d82fc JJ |
573 | }); |
574 | } | |
575 | ||
576 | fn assemble_inherent_candidates_from_param(&mut self, | |
577 | _rcvr_ty: Ty<'tcx>, | |
578 | param_ty: ty::ParamTy) { | |
579 | // FIXME -- Do we want to commit to this behavior for param bounds? | |
580 | ||
7cac9316 | 581 | let bounds: Vec<_> = self.param_env |
c30ab7b3 | 582 | .caller_bounds |
1a4d82fc JJ |
583 | .iter() |
584 | .filter_map(|predicate| { | |
585 | match *predicate { | |
586 | ty::Predicate::Trait(ref trait_predicate) => { | |
587 | match trait_predicate.0.trait_ref.self_ty().sty { | |
62682a34 | 588 | ty::TyParam(ref p) if *p == param_ty => { |
1a4d82fc JJ |
589 | Some(trait_predicate.to_poly_trait_ref()) |
590 | } | |
c30ab7b3 | 591 | _ => None, |
1a4d82fc JJ |
592 | } |
593 | } | |
594 | ty::Predicate::Equate(..) | | |
cc61c64b | 595 | ty::Predicate::Subtype(..) | |
1a4d82fc JJ |
596 | ty::Predicate::Projection(..) | |
597 | ty::Predicate::RegionOutlives(..) | | |
e9174d1e SL |
598 | ty::Predicate::WellFormed(..) | |
599 | ty::Predicate::ObjectSafe(..) | | |
a7813a04 | 600 | ty::Predicate::ClosureKind(..) | |
c30ab7b3 | 601 | ty::Predicate::TypeOutlives(..) => None, |
1a4d82fc JJ |
602 | } |
603 | }) | |
604 | .collect(); | |
605 | ||
c1a9b12d | 606 | self.elaborate_bounds(&bounds, |this, poly_trait_ref, item| { |
c30ab7b3 | 607 | let trait_ref = this.erase_late_bound_regions(&poly_trait_ref); |
1a4d82fc | 608 | |
c30ab7b3 | 609 | let xform_self_ty = this.xform_self_ty(&item, trait_ref.self_ty(), trait_ref.substs); |
1a4d82fc | 610 | |
1a4d82fc JJ |
611 | // Because this trait derives from a where-clause, it |
612 | // should not contain any inference variables or other | |
613 | // artifacts. This means it is safe to put into the | |
614 | // `WhereClauseCandidate` and (eventually) into the | |
615 | // `WhereClausePick`. | |
9e0c209e | 616 | assert!(!trait_ref.substs.needs_infer()); |
1a4d82fc | 617 | |
7cac9316 XL |
618 | this.push_inherent_candidate(xform_self_ty, item, |
619 | WhereClauseCandidate(poly_trait_ref), None); | |
1a4d82fc JJ |
620 | }); |
621 | } | |
622 | ||
623 | // Do a search through a list of bounds, using a callback to actually | |
624 | // create the candidates. | |
c30ab7b3 SL |
625 | fn elaborate_bounds<F>(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) |
626 | where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, | |
627 | ty::PolyTraitRef<'tcx>, | |
476ff2be | 628 | ty::AssociatedItem) |
1a4d82fc | 629 | { |
62682a34 | 630 | debug!("elaborate_bounds(bounds={:?})", bounds); |
1a4d82fc | 631 | |
a7813a04 | 632 | let tcx = self.tcx; |
1a4d82fc | 633 | for bound_trait_ref in traits::transitive_bounds(tcx, bounds) { |
32a655c1 SL |
634 | for item in self.impl_or_trait_item(bound_trait_ref.def_id()) { |
635 | if !self.has_applicable_self(&item) { | |
636 | self.record_static_candidate(TraitSource(bound_trait_ref.def_id())); | |
637 | } else { | |
638 | mk_cand(self, bound_trait_ref, item); | |
c30ab7b3 | 639 | } |
1a4d82fc JJ |
640 | } |
641 | } | |
642 | } | |
643 | ||
644 | fn assemble_extension_candidates_for_traits_in_scope(&mut self, | |
645 | expr_id: ast::NodeId) | |
c30ab7b3 | 646 | -> Result<(), MethodError<'tcx>> { |
476ff2be | 647 | let mut duplicates = FxHashSet(); |
5bcae85e | 648 | let opt_applicable_traits = self.tcx.trait_map.get(&expr_id); |
85aaf69f | 649 | if let Some(applicable_traits) = opt_applicable_traits { |
a7813a04 XL |
650 | for trait_candidate in applicable_traits { |
651 | let trait_did = trait_candidate.def_id; | |
1a4d82fc | 652 | if duplicates.insert(trait_did) { |
8bb4bdeb XL |
653 | let import_id = trait_candidate.import_id; |
654 | let result = self.assemble_extension_candidates_for_trait(import_id, trait_did); | |
a7813a04 | 655 | result?; |
1a4d82fc JJ |
656 | } |
657 | } | |
658 | } | |
85aaf69f SL |
659 | Ok(()) |
660 | } | |
661 | ||
62682a34 | 662 | fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(), MethodError<'tcx>> { |
476ff2be | 663 | let mut duplicates = FxHashSet(); |
8bb4bdeb | 664 | for trait_info in suggest::all_traits(self.tcx) { |
85aaf69f | 665 | if duplicates.insert(trait_info.def_id) { |
8bb4bdeb | 666 | self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?; |
85aaf69f SL |
667 | } |
668 | } | |
669 | Ok(()) | |
1a4d82fc JJ |
670 | } |
671 | ||
32a655c1 SL |
672 | pub fn matches_return_type(&self, method: &ty::AssociatedItem, |
673 | expected: ty::Ty<'tcx>) -> bool { | |
674 | match method.def() { | |
675 | Def::Method(def_id) => { | |
041b39d2 | 676 | let fty = self.tcx.fn_sig(def_id); |
32a655c1 SL |
677 | self.probe(|_| { |
678 | let substs = self.fresh_substs_for_item(self.span, method.def_id); | |
679 | let output = fty.output().subst(self.tcx, substs); | |
680 | let (output, _) = self.replace_late_bound_regions_with_fresh_var( | |
681 | self.span, infer::FnCall, &output); | |
7cac9316 | 682 | self.can_sub(self.param_env, output, expected).is_ok() |
32a655c1 SL |
683 | }) |
684 | } | |
685 | _ => false, | |
686 | } | |
687 | } | |
688 | ||
1a4d82fc | 689 | fn assemble_extension_candidates_for_trait(&mut self, |
8bb4bdeb | 690 | import_id: Option<ast::NodeId>, |
e9174d1e | 691 | trait_def_id: DefId) |
c30ab7b3 | 692 | -> Result<(), MethodError<'tcx>> { |
62682a34 SL |
693 | debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", |
694 | trait_def_id); | |
1a4d82fc | 695 | |
32a655c1 SL |
696 | for item in self.impl_or_trait_item(trait_def_id) { |
697 | // Check whether `trait_def_id` defines a method with suitable name: | |
698 | if !self.has_applicable_self(&item) { | |
699 | debug!("method has inapplicable self"); | |
700 | self.record_static_candidate(TraitSource(trait_def_id)); | |
701 | continue; | |
c30ab7b3 | 702 | } |
1a4d82fc | 703 | |
8bb4bdeb XL |
704 | self.assemble_extension_candidates_for_trait_impls(import_id, trait_def_id, |
705 | item.clone()); | |
1a4d82fc | 706 | |
8bb4bdeb | 707 | self.assemble_closure_candidates(import_id, trait_def_id, item.clone())?; |
1a4d82fc | 708 | |
8bb4bdeb | 709 | self.assemble_projection_candidates(import_id, trait_def_id, item.clone()); |
1a4d82fc | 710 | |
8bb4bdeb | 711 | self.assemble_where_clause_candidates(import_id, trait_def_id, item.clone()); |
32a655c1 | 712 | } |
85aaf69f SL |
713 | |
714 | Ok(()) | |
1a4d82fc JJ |
715 | } |
716 | ||
717 | fn assemble_extension_candidates_for_trait_impls(&mut self, | |
8bb4bdeb | 718 | import_id: Option<ast::NodeId>, |
e9174d1e | 719 | trait_def_id: DefId, |
476ff2be | 720 | item: ty::AssociatedItem) { |
d9579d0f | 721 | // FIXME(arielb1): can we use for_each_relevant_impl here? |
041b39d2 | 722 | self.tcx.for_each_impl(trait_def_id, |impl_def_id| { |
62682a34 SL |
723 | debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={:?} \ |
724 | impl_def_id={:?}", | |
725 | trait_def_id, | |
726 | impl_def_id); | |
1a4d82fc JJ |
727 | |
728 | if !self.impl_can_possibly_match(impl_def_id) { | |
d9579d0f | 729 | return; |
1a4d82fc JJ |
730 | } |
731 | ||
c34b1796 | 732 | let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id); |
1a4d82fc | 733 | |
62682a34 | 734 | debug!("impl_substs={:?}", impl_substs); |
1a4d82fc | 735 | |
c30ab7b3 | 736 | let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id) |
1a4d82fc | 737 | .unwrap() // we know this is a trait impl |
9e0c209e | 738 | .subst(self.tcx, impl_substs); |
1a4d82fc | 739 | |
62682a34 | 740 | debug!("impl_trait_ref={:?}", impl_trait_ref); |
1a4d82fc JJ |
741 | |
742 | // Determine the receiver type that the method itself expects. | |
743 | let xform_self_ty = | |
c30ab7b3 | 744 | self.xform_self_ty(&item, impl_trait_ref.self_ty(), impl_trait_ref.substs); |
1a4d82fc | 745 | |
62682a34 SL |
746 | // Normalize the receiver. We can't use normalize_associated_types_in |
747 | // as it will pollute the fcx's fulfillment context after this probe | |
748 | // is over. | |
a7813a04 XL |
749 | let cause = traits::ObligationCause::misc(self.span, self.body_id); |
750 | let mut selcx = &mut traits::SelectionContext::new(self.fcx); | |
62682a34 | 751 | let traits::Normalized { value: xform_self_ty, obligations } = |
7cac9316 | 752 | traits::normalize(selcx, self.param_env, cause, &xform_self_ty); |
62682a34 SL |
753 | |
754 | debug!("xform_self_ty={:?}", xform_self_ty); | |
1a4d82fc | 755 | |
7cac9316 XL |
756 | self.push_extension_candidate(xform_self_ty, item, |
757 | ExtensionImplCandidate(impl_def_id, impl_substs, obligations), import_id); | |
d9579d0f | 758 | }); |
1a4d82fc JJ |
759 | } |
760 | ||
e9174d1e | 761 | fn impl_can_possibly_match(&self, impl_def_id: DefId) -> bool { |
1a4d82fc JJ |
762 | let simplified_steps = match self.opt_simplified_steps { |
763 | Some(ref simplified_steps) => simplified_steps, | |
c30ab7b3 SL |
764 | None => { |
765 | return true; | |
766 | } | |
1a4d82fc JJ |
767 | }; |
768 | ||
7cac9316 | 769 | let impl_type = self.tcx.type_of(impl_def_id); |
1a4d82fc | 770 | let impl_simplified_type = |
476ff2be | 771 | match ty::fast_reject::simplify_type(self.tcx, impl_type, false) { |
1a4d82fc | 772 | Some(simplified_type) => simplified_type, |
c30ab7b3 SL |
773 | None => { |
774 | return true; | |
775 | } | |
1a4d82fc JJ |
776 | }; |
777 | ||
778 | simplified_steps.contains(&impl_simplified_type) | |
779 | } | |
780 | ||
85aaf69f | 781 | fn assemble_closure_candidates(&mut self, |
8bb4bdeb | 782 | import_id: Option<ast::NodeId>, |
e9174d1e | 783 | trait_def_id: DefId, |
476ff2be | 784 | item: ty::AssociatedItem) |
c30ab7b3 | 785 | -> Result<(), MethodError<'tcx>> { |
1a4d82fc | 786 | // Check if this is one of the Fn,FnMut,FnOnce traits. |
a7813a04 | 787 | let tcx = self.tcx; |
1a4d82fc | 788 | let kind = if Some(trait_def_id) == tcx.lang_items.fn_trait() { |
54a0048b | 789 | ty::ClosureKind::Fn |
1a4d82fc | 790 | } else if Some(trait_def_id) == tcx.lang_items.fn_mut_trait() { |
54a0048b | 791 | ty::ClosureKind::FnMut |
1a4d82fc | 792 | } else if Some(trait_def_id) == tcx.lang_items.fn_once_trait() { |
54a0048b | 793 | ty::ClosureKind::FnOnce |
1a4d82fc | 794 | } else { |
85aaf69f | 795 | return Ok(()); |
1a4d82fc JJ |
796 | }; |
797 | ||
798 | // Check if there is an unboxed-closure self-type in the list of receivers. | |
799 | // If so, add "synthetic impls". | |
800 | let steps = self.steps.clone(); | |
62682a34 | 801 | for step in steps.iter() { |
32a655c1 SL |
802 | let closure_id = match step.self_ty.sty { |
803 | ty::TyClosure(def_id, _) => { | |
804 | if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { | |
805 | id | |
806 | } else { | |
807 | continue; | |
808 | } | |
809 | } | |
1a4d82fc JJ |
810 | _ => continue, |
811 | }; | |
812 | ||
a7813a04 | 813 | let closure_kinds = &self.tables.borrow().closure_kinds; |
32a655c1 | 814 | let closure_kind = match closure_kinds.get(&closure_id) { |
7cac9316 | 815 | Some(&(k, _)) => k, |
1a4d82fc | 816 | None => { |
85aaf69f | 817 | return Err(MethodError::ClosureAmbiguity(trait_def_id)); |
1a4d82fc JJ |
818 | } |
819 | }; | |
820 | ||
821 | // this closure doesn't implement the right kind of `Fn` trait | |
c34b1796 | 822 | if !closure_kind.extends(kind) { |
1a4d82fc JJ |
823 | continue; |
824 | } | |
825 | ||
826 | // create some substitutions for the argument/return type; | |
827 | // for the purposes of our method lookup, we only take | |
828 | // receiver type into account, so we can just substitute | |
829 | // fresh types here to use during substitution and subtyping. | |
c30ab7b3 SL |
830 | let substs = Substs::for_item(self.tcx, |
831 | trait_def_id, | |
832 | |def, _| self.region_var_for_def(self.span, def), | |
833 | |def, substs| { | |
9e0c209e SL |
834 | if def.index == 0 { |
835 | step.self_ty | |
836 | } else { | |
837 | self.type_var_for_def(self.span, def, substs) | |
838 | } | |
839 | }); | |
1a4d82fc | 840 | |
c30ab7b3 | 841 | let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs); |
7cac9316 | 842 | self.push_inherent_candidate(xform_self_ty, item, TraitCandidate, import_id); |
1a4d82fc | 843 | } |
85aaf69f SL |
844 | |
845 | Ok(()) | |
1a4d82fc JJ |
846 | } |
847 | ||
848 | fn assemble_projection_candidates(&mut self, | |
8bb4bdeb | 849 | import_id: Option<ast::NodeId>, |
e9174d1e | 850 | trait_def_id: DefId, |
476ff2be | 851 | item: ty::AssociatedItem) { |
1a4d82fc | 852 | debug!("assemble_projection_candidates(\ |
62682a34 | 853 | trait_def_id={:?}, \ |
c1a9b12d | 854 | item={:?})", |
62682a34 | 855 | trait_def_id, |
c1a9b12d | 856 | item); |
1a4d82fc | 857 | |
7cac9316 | 858 | for step in Rc::clone(&self.steps).iter() { |
c30ab7b3 | 859 | debug!("assemble_projection_candidates: step={:?}", step); |
1a4d82fc | 860 | |
5bcae85e | 861 | let (def_id, substs) = match step.self_ty.sty { |
041b39d2 XL |
862 | ty::TyProjection(ref data) => { |
863 | let trait_ref = data.trait_ref(self.tcx); | |
864 | (trait_ref.def_id, trait_ref.substs) | |
865 | }, | |
5bcae85e | 866 | ty::TyAnon(def_id, substs) => (def_id, substs), |
1a4d82fc JJ |
867 | _ => continue, |
868 | }; | |
869 | ||
5bcae85e | 870 | debug!("assemble_projection_candidates: def_id={:?} substs={:?}", |
c30ab7b3 SL |
871 | def_id, |
872 | substs); | |
1a4d82fc | 873 | |
7cac9316 | 874 | let trait_predicates = self.tcx.predicates_of(def_id); |
5bcae85e | 875 | let bounds = trait_predicates.instantiate(self.tcx, substs); |
9e0c209e | 876 | let predicates = bounds.predicates; |
62682a34 SL |
877 | debug!("assemble_projection_candidates: predicates={:?}", |
878 | predicates); | |
c30ab7b3 | 879 | for poly_bound in traits::elaborate_predicates(self.tcx, predicates) |
1a4d82fc | 880 | .filter_map(|p| p.to_opt_poly_trait_ref()) |
c30ab7b3 | 881 | .filter(|b| b.def_id() == trait_def_id) { |
1a4d82fc JJ |
882 | let bound = self.erase_late_bound_regions(&poly_bound); |
883 | ||
5bcae85e | 884 | debug!("assemble_projection_candidates: def_id={:?} substs={:?} bound={:?}", |
c30ab7b3 SL |
885 | def_id, |
886 | substs, | |
887 | bound); | |
1a4d82fc | 888 | |
7cac9316 | 889 | if self.can_eq(self.param_env, step.self_ty, bound.self_ty()).is_ok() { |
c30ab7b3 | 890 | let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs); |
1a4d82fc | 891 | |
62682a34 SL |
892 | debug!("assemble_projection_candidates: bound={:?} xform_self_ty={:?}", |
893 | bound, | |
894 | xform_self_ty); | |
1a4d82fc | 895 | |
7cac9316 | 896 | self.push_extension_candidate(xform_self_ty, item, TraitCandidate, import_id); |
1a4d82fc JJ |
897 | } |
898 | } | |
899 | } | |
900 | } | |
901 | ||
902 | fn assemble_where_clause_candidates(&mut self, | |
8bb4bdeb | 903 | import_id: Option<ast::NodeId>, |
e9174d1e | 904 | trait_def_id: DefId, |
476ff2be | 905 | item: ty::AssociatedItem) { |
62682a34 SL |
906 | debug!("assemble_where_clause_candidates(trait_def_id={:?})", |
907 | trait_def_id); | |
1a4d82fc | 908 | |
7cac9316 | 909 | let caller_predicates = self.param_env.caller_bounds.to_vec(); |
a7813a04 | 910 | for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates) |
c30ab7b3 SL |
911 | .filter_map(|p| p.to_opt_poly_trait_ref()) |
912 | .filter(|b| b.def_id() == trait_def_id) { | |
1a4d82fc | 913 | let bound = self.erase_late_bound_regions(&poly_bound); |
c30ab7b3 | 914 | let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs); |
1a4d82fc | 915 | |
62682a34 SL |
916 | debug!("assemble_where_clause_candidates: bound={:?} xform_self_ty={:?}", |
917 | bound, | |
918 | xform_self_ty); | |
1a4d82fc | 919 | |
7cac9316 XL |
920 | self.push_extension_candidate(xform_self_ty, item, |
921 | WhereClauseCandidate(poly_bound), import_id); | |
1a4d82fc JJ |
922 | } |
923 | } | |
924 | ||
32a655c1 SL |
925 | fn candidate_method_names(&self) -> Vec<ast::Name> { |
926 | let mut set = FxHashSet(); | |
927 | let mut names: Vec<_> = | |
928 | self.inherent_candidates | |
929 | .iter() | |
930 | .chain(&self.extension_candidates) | |
931 | .map(|candidate| candidate.item.name) | |
932 | .filter(|&name| set.insert(name)) | |
933 | .collect(); | |
934 | ||
935 | // sort them by the name so we have a stable result | |
936 | names.sort_by_key(|n| n.as_str()); | |
937 | names | |
938 | } | |
939 | ||
1a4d82fc JJ |
940 | /////////////////////////////////////////////////////////////////////////// |
941 | // THE ACTUAL SEARCH | |
942 | ||
943 | fn pick(mut self) -> PickResult<'tcx> { | |
32a655c1 SL |
944 | assert!(match self.looking_for { |
945 | LookingFor::MethodName(_) => true, | |
946 | LookingFor::ReturnType(_) => false, | |
947 | }); | |
948 | ||
3157f602 XL |
949 | if let Some(r) = self.pick_core() { |
950 | return r; | |
85aaf69f | 951 | } |
1a4d82fc | 952 | |
85aaf69f | 953 | let static_candidates = mem::replace(&mut self.static_candidates, vec![]); |
54a0048b | 954 | let private_candidate = mem::replace(&mut self.private_candidate, None); |
62682a34 | 955 | let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]); |
85aaf69f SL |
956 | |
957 | // things failed, so lets look at all traits, for diagnostic purposes now: | |
958 | self.reset(); | |
959 | ||
960 | let span = self.span; | |
a7813a04 | 961 | let tcx = self.tcx; |
85aaf69f | 962 | |
54a0048b | 963 | self.assemble_extension_candidates_for_all_traits()?; |
85aaf69f SL |
964 | |
965 | let out_of_scope_traits = match self.pick_core() { | |
476ff2be | 966 | Some(Ok(p)) => vec![p.item.container.id()], |
32a655c1 | 967 | //Some(Ok(p)) => p.iter().map(|p| p.item.container().id()).collect(), |
c30ab7b3 SL |
968 | Some(Err(MethodError::Ambiguity(v))) => { |
969 | v.into_iter() | |
970 | .map(|source| { | |
971 | match source { | |
972 | TraitSource(id) => id, | |
973 | ImplSource(impl_id) => { | |
974 | match tcx.trait_id_of_impl(impl_id) { | |
975 | Some(id) => id, | |
976 | None => { | |
977 | span_bug!(span, | |
978 | "found inherent method when looking at traits") | |
979 | } | |
980 | } | |
981 | } | |
85aaf69f | 982 | } |
c30ab7b3 SL |
983 | }) |
984 | .collect() | |
985 | } | |
62682a34 | 986 | Some(Err(MethodError::NoMatch(NoMatchData { out_of_scope_traits: others, .. }))) => { |
85aaf69f SL |
987 | assert!(others.is_empty()); |
988 | vec![] | |
1a4d82fc | 989 | } |
85aaf69f SL |
990 | Some(Err(MethodError::ClosureAmbiguity(..))) => { |
991 | // this error only occurs when assembling candidates | |
54a0048b | 992 | span_bug!(span, "encountered ClosureAmbiguity from pick_core"); |
85aaf69f | 993 | } |
54a0048b | 994 | _ => vec![], |
85aaf69f SL |
995 | }; |
996 | ||
54a0048b SL |
997 | if let Some(def) = private_candidate { |
998 | return Err(MethodError::PrivateMatch(def)); | |
999 | } | |
1000 | ||
c30ab7b3 SL |
1001 | Err(MethodError::NoMatch(NoMatchData::new(static_candidates, |
1002 | unsatisfied_predicates, | |
1003 | out_of_scope_traits, | |
1004 | self.mode))) | |
85aaf69f SL |
1005 | } |
1006 | ||
1007 | fn pick_core(&mut self) -> Option<PickResult<'tcx>> { | |
1008 | let steps = self.steps.clone(); | |
1a4d82fc | 1009 | |
85aaf69f SL |
1010 | // find the first step that works |
1011 | steps.iter().filter_map(|step| self.pick_step(step)).next() | |
1a4d82fc JJ |
1012 | } |
1013 | ||
1014 | fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> { | |
62682a34 | 1015 | debug!("pick_step: step={:?}", step); |
1a4d82fc | 1016 | |
c1a9b12d | 1017 | if step.self_ty.references_error() { |
1a4d82fc JJ |
1018 | return None; |
1019 | } | |
1020 | ||
3157f602 XL |
1021 | if let Some(result) = self.pick_by_value_method(step) { |
1022 | return Some(result); | |
1a4d82fc JJ |
1023 | } |
1024 | ||
1025 | self.pick_autorefd_method(step) | |
1026 | } | |
1027 | ||
c30ab7b3 SL |
1028 | fn pick_by_value_method(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> { |
1029 | //! For each type `T` in the step list, this attempts to find a | |
1030 | //! method where the (transformed) self type is exactly `T`. We | |
1031 | //! do however do one transformation on the adjustment: if we | |
1032 | //! are passing a region pointer in, we will potentially | |
1033 | //! *reborrow* it to a shorter lifetime. This allows us to | |
1034 | //! transparently pass `&mut` pointers, in particular, without | |
1035 | //! consuming them for their entire lifetime. | |
1a4d82fc | 1036 | |
9346a6ac AL |
1037 | if step.unsize { |
1038 | return None; | |
1039 | } | |
1a4d82fc | 1040 | |
c30ab7b3 SL |
1041 | self.pick_method(step.self_ty).map(|r| { |
1042 | r.map(|mut pick| { | |
1043 | pick.autoderefs = step.autoderefs; | |
1a4d82fc | 1044 | |
c30ab7b3 SL |
1045 | // Insert a `&*` or `&mut *` if this is a reference type: |
1046 | if let ty::TyRef(_, mt) = step.self_ty.sty { | |
1047 | pick.autoderefs += 1; | |
1048 | pick.autoref = Some(mt.mutbl); | |
1049 | } | |
9346a6ac | 1050 | |
c30ab7b3 SL |
1051 | pick |
1052 | }) | |
1053 | }) | |
1a4d82fc JJ |
1054 | } |
1055 | ||
c30ab7b3 | 1056 | fn pick_autorefd_method(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> { |
a7813a04 | 1057 | let tcx = self.tcx; |
1a4d82fc | 1058 | |
1a4d82fc JJ |
1059 | // In general, during probing we erase regions. See |
1060 | // `impl_self_ty()` for an explanation. | |
cc61c64b | 1061 | let region = tcx.types.re_erased; |
1a4d82fc JJ |
1062 | |
1063 | // Search through mutabilities in order to find one where pick works: | |
c30ab7b3 SL |
1064 | [hir::MutImmutable, hir::MutMutable] |
1065 | .iter() | |
1066 | .filter_map(|&m| { | |
1067 | let autoref_ty = tcx.mk_ref(region, | |
1068 | ty::TypeAndMut { | |
1069 | ty: step.self_ty, | |
1070 | mutbl: m, | |
1071 | }); | |
1072 | self.pick_method(autoref_ty).map(|r| { | |
1073 | r.map(|mut pick| { | |
1074 | pick.autoderefs = step.autoderefs; | |
1075 | pick.autoref = Some(m); | |
1076 | pick.unsize = if step.unsize { | |
1077 | Some(step.self_ty) | |
1078 | } else { | |
1079 | None | |
1080 | }; | |
1081 | pick | |
1082 | }) | |
1083 | }) | |
1084 | }) | |
1085 | .nth(0) | |
1a4d82fc JJ |
1086 | } |
1087 | ||
1088 | fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> { | |
a7813a04 | 1089 | debug!("pick_method(self_ty={})", self.ty_to_string(self_ty)); |
1a4d82fc | 1090 | |
62682a34 SL |
1091 | let mut possibly_unsatisfied_predicates = Vec::new(); |
1092 | ||
1a4d82fc | 1093 | debug!("searching inherent candidates"); |
3157f602 XL |
1094 | if let Some(pick) = self.consider_candidates(self_ty, |
1095 | &self.inherent_candidates, | |
1096 | &mut possibly_unsatisfied_predicates) { | |
1097 | return Some(pick); | |
1a4d82fc JJ |
1098 | } |
1099 | ||
1100 | debug!("searching extension candidates"); | |
c30ab7b3 SL |
1101 | let res = self.consider_candidates(self_ty, |
1102 | &self.extension_candidates, | |
62682a34 SL |
1103 | &mut possibly_unsatisfied_predicates); |
1104 | if let None = res { | |
1105 | self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates); | |
1106 | } | |
1107 | res | |
1a4d82fc JJ |
1108 | } |
1109 | ||
1110 | fn consider_candidates(&self, | |
1111 | self_ty: Ty<'tcx>, | |
62682a34 SL |
1112 | probes: &[Candidate<'tcx>], |
1113 | possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>) | |
1a4d82fc | 1114 | -> Option<PickResult<'tcx>> { |
c30ab7b3 SL |
1115 | let mut applicable_candidates: Vec<_> = probes.iter() |
1116 | .filter(|&probe| self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates)) | |
1117 | .collect(); | |
1a4d82fc | 1118 | |
62682a34 | 1119 | debug!("applicable_candidates: {:?}", applicable_candidates); |
1a4d82fc JJ |
1120 | |
1121 | if applicable_candidates.len() > 1 { | |
85aaf69f | 1122 | match self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) { |
c30ab7b3 SL |
1123 | Some(pick) => { |
1124 | return Some(Ok(pick)); | |
1125 | } | |
1126 | None => {} | |
1a4d82fc JJ |
1127 | } |
1128 | } | |
1129 | ||
1130 | if applicable_candidates.len() > 1 { | |
1131 | let sources = probes.iter().map(|p| p.to_source()).collect(); | |
85aaf69f | 1132 | return Some(Err(MethodError::Ambiguity(sources))); |
1a4d82fc JJ |
1133 | } |
1134 | ||
c30ab7b3 | 1135 | applicable_candidates.pop().map(|probe| Ok(probe.to_unadjusted_pick())) |
1a4d82fc JJ |
1136 | } |
1137 | ||
c30ab7b3 SL |
1138 | fn consider_probe(&self, |
1139 | self_ty: Ty<'tcx>, | |
1140 | probe: &Candidate<'tcx>, | |
1141 | possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>) | |
1142 | -> bool { | |
1143 | debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); | |
1a4d82fc | 1144 | |
a7813a04 | 1145 | self.probe(|_| { |
1a4d82fc | 1146 | // First check that the self type can be related. |
7cac9316 XL |
1147 | let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env) |
1148 | .sup(probe.xform_self_ty, self_ty) { | |
cc61c64b | 1149 | Ok(InferOk { obligations, value: () }) => obligations, |
1a4d82fc JJ |
1150 | Err(_) => { |
1151 | debug!("--> cannot relate self-types"); | |
1152 | return false; | |
1153 | } | |
cc61c64b | 1154 | }; |
1a4d82fc JJ |
1155 | |
1156 | // If so, impls may carry other conditions (e.g., where | |
1157 | // clauses) that must be considered. Make sure that those | |
1158 | // match as well (or at least may match, sometimes we | |
1159 | // don't have enough information to fully evaluate). | |
c1a9b12d SL |
1160 | let (impl_def_id, substs, ref_obligations) = match probe.kind { |
1161 | InherentImplCandidate(ref substs, ref ref_obligations) => { | |
476ff2be | 1162 | (probe.item.container.id(), substs, ref_obligations) |
c1a9b12d SL |
1163 | } |
1164 | ||
1165 | ExtensionImplCandidate(impl_def_id, ref substs, ref ref_obligations) => { | |
1166 | (impl_def_id, substs, ref_obligations) | |
1a4d82fc JJ |
1167 | } |
1168 | ||
92a42be0 | 1169 | ObjectCandidate | |
c1a9b12d | 1170 | TraitCandidate | |
1a4d82fc JJ |
1171 | WhereClauseCandidate(..) => { |
1172 | // These have no additional conditions to check. | |
c1a9b12d SL |
1173 | return true; |
1174 | } | |
1175 | }; | |
1176 | ||
a7813a04 XL |
1177 | let selcx = &mut traits::SelectionContext::new(self); |
1178 | let cause = traits::ObligationCause::misc(self.span, self.body_id); | |
c1a9b12d SL |
1179 | |
1180 | // Check whether the impl imposes obligations we have to worry about. | |
7cac9316 | 1181 | let impl_bounds = self.tcx.predicates_of(impl_def_id); |
a7813a04 | 1182 | let impl_bounds = impl_bounds.instantiate(self.tcx, substs); |
c30ab7b3 | 1183 | let traits::Normalized { value: impl_bounds, obligations: norm_obligations } = |
7cac9316 | 1184 | traits::normalize(selcx, self.param_env, cause.clone(), &impl_bounds); |
c1a9b12d SL |
1185 | |
1186 | // Convert the bounds into obligations. | |
7cac9316 XL |
1187 | let obligations = traits::predicates_for_generics(cause.clone(), |
1188 | self.param_env, | |
1189 | &impl_bounds); | |
c1a9b12d SL |
1190 | debug!("impl_obligations={:?}", obligations); |
1191 | ||
1192 | // Evaluate those obligations to see if they might possibly hold. | |
1193 | let mut all_true = true; | |
1194 | for o in obligations.iter() | |
cc61c64b | 1195 | .chain(sub_obligations.iter()) |
c1a9b12d SL |
1196 | .chain(norm_obligations.iter()) |
1197 | .chain(ref_obligations.iter()) { | |
1198 | if !selcx.evaluate_obligation(o) { | |
1199 | all_true = false; | |
1200 | if let &ty::Predicate::Trait(ref pred) = &o.predicate { | |
1201 | possibly_unsatisfied_predicates.push(pred.0.trait_ref); | |
1202 | } | |
1a4d82fc JJ |
1203 | } |
1204 | } | |
c1a9b12d | 1205 | all_true |
1a4d82fc JJ |
1206 | }) |
1207 | } | |
1208 | ||
1209 | /// Sometimes we get in a situation where we have multiple probes that are all impls of the | |
1210 | /// same trait, but we don't know which impl to use. In this case, since in all cases the | |
1211 | /// external interface of the method can be determined from the trait, it's ok not to decide. | |
1212 | /// We can basically just collapse all of the probes for various impls into one where-clause | |
1213 | /// probe. This will result in a pending obligation so when more type-info is available we can | |
1214 | /// make the final decision. | |
1215 | /// | |
1216 | /// Example (`src/test/run-pass/method-two-trait-defer-resolution-1.rs`): | |
1217 | /// | |
1218 | /// ``` | |
1219 | /// trait Foo { ... } | |
1220 | /// impl Foo for Vec<int> { ... } | |
c34b1796 | 1221 | /// impl Foo for Vec<usize> { ... } |
1a4d82fc JJ |
1222 | /// ``` |
1223 | /// | |
1224 | /// Now imagine the receiver is `Vec<_>`. It doesn't really matter at this time which impl we | |
1225 | /// use, so it's ok to just commit to "using the method from the trait Foo". | |
c30ab7b3 | 1226 | fn collapse_candidates_to_trait_pick(&self, probes: &[&Candidate<'tcx>]) -> Option<Pick<'tcx>> { |
1a4d82fc | 1227 | // Do all probes correspond to the same trait? |
476ff2be | 1228 | let container = probes[0].item.container; |
c1a9b12d SL |
1229 | match container { |
1230 | ty::TraitContainer(_) => {} | |
c30ab7b3 | 1231 | ty::ImplContainer(_) => return None, |
c1a9b12d | 1232 | } |
476ff2be | 1233 | if probes[1..].iter().any(|p| p.item.container != container) { |
1a4d82fc JJ |
1234 | return None; |
1235 | } | |
1236 | ||
1237 | // If so, just use this trait and call it a day. | |
1a4d82fc | 1238 | Some(Pick { |
c1a9b12d SL |
1239 | item: probes[0].item.clone(), |
1240 | kind: TraitPick, | |
a7813a04 | 1241 | import_id: probes[0].import_id, |
9346a6ac AL |
1242 | autoderefs: 0, |
1243 | autoref: None, | |
c30ab7b3 | 1244 | unsize: None, |
1a4d82fc JJ |
1245 | }) |
1246 | } | |
1247 | ||
1248 | /////////////////////////////////////////////////////////////////////////// | |
1249 | // MISCELLANY | |
476ff2be SL |
1250 | fn has_applicable_self(&self, item: &ty::AssociatedItem) -> bool { |
1251 | // "Fast track" -- check for usage of sugar when in method call | |
1252 | // mode. | |
1253 | // | |
1254 | // In Path mode (i.e., resolving a value like `T::next`), consider any | |
1255 | // associated value (i.e., methods, constants) but not types. | |
1256 | match self.mode { | |
1257 | Mode::MethodCall => item.method_has_self_argument, | |
1258 | Mode::Path => match item.kind { | |
1259 | ty::AssociatedKind::Type => false, | |
1260 | ty::AssociatedKind::Method | ty::AssociatedKind::Const => true | |
1261 | }, | |
1a4d82fc | 1262 | } |
1a4d82fc JJ |
1263 | // FIXME -- check for types that deref to `Self`, |
1264 | // like `Rc<Self>` and so on. | |
1265 | // | |
1266 | // Note also that the current code will break if this type | |
1267 | // includes any of the type parameters defined on the method | |
1268 | // -- but this could be overcome. | |
1a4d82fc JJ |
1269 | } |
1270 | ||
1271 | fn record_static_candidate(&mut self, source: CandidateSource) { | |
1272 | self.static_candidates.push(source); | |
1273 | } | |
1274 | ||
1275 | fn xform_self_ty(&self, | |
476ff2be | 1276 | item: &ty::AssociatedItem, |
c34b1796 | 1277 | impl_ty: Ty<'tcx>, |
9e0c209e | 1278 | substs: &Substs<'tcx>) |
c30ab7b3 | 1279 | -> Ty<'tcx> { |
476ff2be SL |
1280 | if item.kind == ty::AssociatedKind::Method && self.mode == Mode::MethodCall { |
1281 | self.xform_method_self_ty(item.def_id, impl_ty, substs) | |
1282 | } else { | |
1283 | impl_ty | |
d9579d0f AL |
1284 | } |
1285 | } | |
1286 | ||
1287 | fn xform_method_self_ty(&self, | |
476ff2be | 1288 | method: DefId, |
d9579d0f | 1289 | impl_ty: Ty<'tcx>, |
9e0c209e | 1290 | substs: &Substs<'tcx>) |
c30ab7b3 | 1291 | -> Ty<'tcx> { |
041b39d2 | 1292 | let self_ty = self.tcx.fn_sig(method).input(0); |
62682a34 SL |
1293 | debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", |
1294 | impl_ty, | |
476ff2be | 1295 | self_ty, |
62682a34 | 1296 | substs); |
1a4d82fc JJ |
1297 | |
1298 | assert!(!substs.has_escaping_regions()); | |
1299 | ||
1300 | // It is possible for type parameters or early-bound lifetimes | |
1301 | // to appear in the signature of `self`. The substitutions we | |
1302 | // are given do not include type/lifetime parameters for the | |
1303 | // method yet. So create fresh variables here for those too, | |
1304 | // if there are any. | |
7cac9316 | 1305 | let generics = self.tcx.generics_of(method); |
476ff2be SL |
1306 | assert_eq!(substs.types().count(), generics.parent_types as usize); |
1307 | assert_eq!(substs.regions().count(), generics.parent_regions as usize); | |
c34b1796 | 1308 | |
1a4d82fc JJ |
1309 | // Erase any late-bound regions from the method and substitute |
1310 | // in the values from the substitution. | |
476ff2be | 1311 | let xform_self_ty = self.erase_late_bound_regions(&self_ty); |
1a4d82fc | 1312 | |
476ff2be | 1313 | if generics.types.is_empty() && generics.regions.is_empty() { |
9e0c209e SL |
1314 | xform_self_ty.subst(self.tcx, substs) |
1315 | } else { | |
476ff2be | 1316 | let substs = Substs::for_item(self.tcx, method, |def, _| { |
9e0c209e | 1317 | let i = def.index as usize; |
8bb4bdeb | 1318 | if i < substs.len() { |
9e0c209e SL |
1319 | substs.region_at(i) |
1320 | } else { | |
1321 | // In general, during probe we erase regions. See | |
1322 | // `impl_self_ty()` for an explanation. | |
cc61c64b | 1323 | self.tcx.types.re_erased |
9e0c209e | 1324 | } |
476ff2be | 1325 | }, |def, cur_substs| { |
9e0c209e | 1326 | let i = def.index as usize; |
8bb4bdeb | 1327 | if i < substs.len() { |
9e0c209e SL |
1328 | substs.type_at(i) |
1329 | } else { | |
1330 | self.type_var_for_def(self.span, def, cur_substs) | |
1331 | } | |
1332 | }); | |
1333 | xform_self_ty.subst(self.tcx, substs) | |
1334 | } | |
1a4d82fc JJ |
1335 | } |
1336 | ||
c34b1796 | 1337 | /// Get the type of an impl and generate substitutions with placeholders. |
c30ab7b3 | 1338 | fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, &'tcx Substs<'tcx>) { |
7cac9316 | 1339 | let impl_ty = self.tcx.type_of(impl_def_id); |
1a4d82fc | 1340 | |
c30ab7b3 SL |
1341 | let substs = Substs::for_item(self.tcx, |
1342 | impl_def_id, | |
cc61c64b | 1343 | |_, _| self.tcx.types.re_erased, |
476ff2be SL |
1344 | |_, _| self.next_ty_var( |
1345 | TypeVariableOrigin::SubstitutionPlaceholder( | |
1346 | self.tcx.def_span(impl_def_id)))); | |
1a4d82fc | 1347 | |
9e0c209e | 1348 | (impl_ty, substs) |
1a4d82fc JJ |
1349 | } |
1350 | ||
1351 | /// Replace late-bound-regions bound by `value` with `'static` using | |
1352 | /// `ty::erase_late_bound_regions`. | |
1353 | /// | |
1354 | /// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of | |
1355 | /// method matching. It is reasonable during the probe phase because we don't consider region | |
1356 | /// relationships at all. Therefore, we can just replace all the region variables with 'static | |
1357 | /// rather than creating fresh region variables. This is nice for two reasons: | |
1358 | /// | |
1359 | /// 1. Because the numbers of the region variables would otherwise be fairly unique to this | |
1360 | /// particular method call, it winds up creating fewer types overall, which helps for memory | |
1361 | /// usage. (Admittedly, this is a rather small effect, though measureable.) | |
1362 | /// | |
1363 | /// 2. It makes it easier to deal with higher-ranked trait bounds, because we can replace any | |
1364 | /// late-bound regions with 'static. Otherwise, if we were going to replace late-bound | |
1365 | /// regions with actual region variables as is proper, we'd have to ensure that the same | |
1366 | /// region got replaced with the same variable, which requires a bit more coordination | |
1367 | /// and/or tracking the substitution and | |
1368 | /// so forth. | |
1369 | fn erase_late_bound_regions<T>(&self, value: &ty::Binder<T>) -> T | |
c30ab7b3 | 1370 | where T: TypeFoldable<'tcx> |
1a4d82fc | 1371 | { |
a7813a04 | 1372 | self.tcx.erase_late_bound_regions(value) |
1a4d82fc | 1373 | } |
1a4d82fc | 1374 | |
32a655c1 SL |
1375 | /// Find the method with the appropriate name (or return type, as the case may be). |
1376 | fn impl_or_trait_item(&self, def_id: DefId) -> Vec<ty::AssociatedItem> { | |
1377 | match self.looking_for { | |
1378 | LookingFor::MethodName(name) => { | |
1379 | self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x]) | |
1380 | } | |
1381 | LookingFor::ReturnType(return_ty) => { | |
1382 | self.tcx | |
1383 | .associated_items(def_id) | |
1384 | .map(|did| self.tcx.associated_item(did.def_id)) | |
1385 | .filter(|m| self.matches_return_type(m, return_ty)) | |
1386 | .collect() | |
1387 | } | |
1388 | } | |
a7813a04 | 1389 | } |
1a4d82fc JJ |
1390 | } |
1391 | ||
1392 | impl<'tcx> Candidate<'tcx> { | |
1393 | fn to_unadjusted_pick(&self) -> Pick<'tcx> { | |
1394 | Pick { | |
d9579d0f | 1395 | item: self.item.clone(), |
1a4d82fc | 1396 | kind: match self.kind { |
9e0c209e | 1397 | InherentImplCandidate(..) => InherentImplPick, |
c30ab7b3 | 1398 | ExtensionImplCandidate(def_id, ..) => ExtensionImplPick(def_id), |
c1a9b12d SL |
1399 | ObjectCandidate => ObjectPick, |
1400 | TraitCandidate => TraitPick, | |
1401 | WhereClauseCandidate(ref trait_ref) => { | |
1a4d82fc JJ |
1402 | // Only trait derived from where-clauses should |
1403 | // appear here, so they should not contain any | |
1404 | // inference variables or other artifacts. This | |
1405 | // means they are safe to put into the | |
1406 | // `WhereClausePick`. | |
9e0c209e | 1407 | assert!(!trait_ref.substs().needs_infer()); |
1a4d82fc | 1408 | |
c1a9b12d | 1409 | WhereClausePick(trait_ref.clone()) |
1a4d82fc | 1410 | } |
9346a6ac | 1411 | }, |
a7813a04 | 1412 | import_id: self.import_id, |
9346a6ac AL |
1413 | autoderefs: 0, |
1414 | autoref: None, | |
c30ab7b3 | 1415 | unsize: None, |
1a4d82fc JJ |
1416 | } |
1417 | } | |
1418 | ||
1419 | fn to_source(&self) -> CandidateSource { | |
1420 | match self.kind { | |
476ff2be | 1421 | InherentImplCandidate(..) => ImplSource(self.item.container.id()), |
9e0c209e | 1422 | ExtensionImplCandidate(def_id, ..) => ImplSource(def_id), |
c1a9b12d SL |
1423 | ObjectCandidate | |
1424 | TraitCandidate | | |
476ff2be | 1425 | WhereClauseCandidate(_) => TraitSource(self.item.container.id()), |
1a4d82fc JJ |
1426 | } |
1427 | } | |
1428 | } |