]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/traits/util.rs
core: Fix size_hint for signed integer Range<T> iterators
[rust.git] / src / librustc / middle / traits / util.rs
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
11 use middle::subst::{Substs, VecPerParamSpace};
12 use middle::infer::InferCtxt;
13 use middle::ty::{self, Ty, AsPredicate, ToPolyTraitRef};
14 use std::fmt;
15 use std::rc::Rc;
16 use syntax::ast;
17 use syntax::codemap::Span;
18 use util::common::ErrorReported;
19 use util::nodemap::FnvHashSet;
20 use util::ppaux::Repr;
21
22 use super::{Obligation, ObligationCause, PredicateObligation,
23             VtableImpl, VtableParam, VtableImplData, VtableDefaultImplData};
24
25 struct PredicateSet<'a,'tcx:'a> {
26     tcx: &'a ty::ctxt<'tcx>,
27     set: FnvHashSet<ty::Predicate<'tcx>>,
28 }
29
30 impl<'a,'tcx> PredicateSet<'a,'tcx> {
31     fn new(tcx: &'a ty::ctxt<'tcx>) -> PredicateSet<'a,'tcx> {
32         PredicateSet { tcx: tcx, set: FnvHashSet() }
33     }
34
35     fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
36         // We have to be careful here because we want
37         //
38         //    for<'a> Foo<&'a int>
39         //
40         // and
41         //
42         //    for<'b> Foo<&'b int>
43         //
44         // to be considered equivalent. So normalize all late-bound
45         // regions before we throw things into the underlying set.
46         let normalized_pred = match *pred {
47             ty::Predicate::Trait(ref data) =>
48                 ty::Predicate::Trait(ty::anonymize_late_bound_regions(self.tcx, data)),
49
50             ty::Predicate::Equate(ref data) =>
51                 ty::Predicate::Equate(ty::anonymize_late_bound_regions(self.tcx, data)),
52
53             ty::Predicate::RegionOutlives(ref data) =>
54                 ty::Predicate::RegionOutlives(ty::anonymize_late_bound_regions(self.tcx, data)),
55
56             ty::Predicate::TypeOutlives(ref data) =>
57                 ty::Predicate::TypeOutlives(ty::anonymize_late_bound_regions(self.tcx, data)),
58
59             ty::Predicate::Projection(ref data) =>
60                 ty::Predicate::Projection(ty::anonymize_late_bound_regions(self.tcx, data)),
61         };
62         self.set.insert(normalized_pred)
63     }
64 }
65
66 ///////////////////////////////////////////////////////////////////////////
67 // `Elaboration` iterator
68 ///////////////////////////////////////////////////////////////////////////
69
70 /// "Elaboration" is the process of identifying all the predicates that
71 /// are implied by a source predicate. Currently this basically means
72 /// walking the "supertraits" and other similar assumptions. For
73 /// example, if we know that `T : Ord`, the elaborator would deduce
74 /// that `T : PartialOrd` holds as well. Similarly, if we have `trait
75 /// Foo : 'static`, and we know that `T : Foo`, then we know that `T :
76 /// 'static`.
77 pub struct Elaborator<'cx, 'tcx:'cx> {
78     tcx: &'cx ty::ctxt<'tcx>,
79     stack: Vec<ty::Predicate<'tcx>>,
80     visited: PredicateSet<'cx,'tcx>,
81 }
82
83 pub fn elaborate_trait_ref<'cx, 'tcx>(
84     tcx: &'cx ty::ctxt<'tcx>,
85     trait_ref: ty::PolyTraitRef<'tcx>)
86     -> Elaborator<'cx, 'tcx>
87 {
88     elaborate_predicates(tcx, vec![trait_ref.as_predicate()])
89 }
90
91 pub fn elaborate_trait_refs<'cx, 'tcx>(
92     tcx: &'cx ty::ctxt<'tcx>,
93     trait_refs: &[ty::PolyTraitRef<'tcx>])
94     -> Elaborator<'cx, 'tcx>
95 {
96     let predicates = trait_refs.iter()
97                                .map(|trait_ref| trait_ref.as_predicate())
98                                .collect();
99     elaborate_predicates(tcx, predicates)
100 }
101
102 pub fn elaborate_predicates<'cx, 'tcx>(
103     tcx: &'cx ty::ctxt<'tcx>,
104     mut predicates: Vec<ty::Predicate<'tcx>>)
105     -> Elaborator<'cx, 'tcx>
106 {
107     let mut visited = PredicateSet::new(tcx);
108     predicates.retain(|pred| visited.insert(pred));
109     Elaborator { tcx: tcx, stack: predicates, visited: visited }
110 }
111
112 impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
113     pub fn filter_to_traits(self) -> FilterToTraits<Elaborator<'cx, 'tcx>> {
114         FilterToTraits::new(self)
115     }
116
117     fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
118         match *predicate {
119             ty::Predicate::Trait(ref data) => {
120                 // Predicates declared on the trait.
121                 let predicates = ty::lookup_super_predicates(self.tcx, data.def_id());
122
123                 let mut predicates: Vec<_> =
124                     predicates.predicates
125                               .iter()
126                               .map(|p| p.subst_supertrait(self.tcx, &data.to_poly_trait_ref()))
127                               .collect();
128
129                 debug!("super_predicates: data={} predicates={}",
130                        data.repr(self.tcx), predicates.repr(self.tcx));
131
132                 // Only keep those bounds that we haven't already
133                 // seen.  This is necessary to prevent infinite
134                 // recursion in some cases.  One common case is when
135                 // people define `trait Sized: Sized { }` rather than `trait
136                 // Sized { }`.
137                 predicates.retain(|r| self.visited.insert(r));
138
139                 self.stack.extend(predicates.into_iter());
140             }
141             ty::Predicate::Equate(..) => {
142                 // Currently, we do not "elaborate" predicates like
143                 // `X == Y`, though conceivably we might. For example,
144                 // `&X == &Y` implies that `X == Y`.
145             }
146             ty::Predicate::Projection(..) => {
147                 // Nothing to elaborate in a projection predicate.
148             }
149             ty::Predicate::RegionOutlives(..) |
150             ty::Predicate::TypeOutlives(..) => {
151                 // Currently, we do not "elaborate" predicates like
152                 // `'a : 'b` or `T : 'a`.  We could conceivably do
153                 // more here.  For example,
154                 //
155                 //     &'a int : 'b
156                 //
157                 // implies that
158                 //
159                 //     'a : 'b
160                 //
161                 // and we could get even more if we took WF
162                 // constraints into account. For example,
163                 //
164                 //     &'a &'b int : 'c
165                 //
166                 // implies that
167                 //
168                 //     'b : 'a
169                 //     'a : 'c
170             }
171         }
172     }
173 }
174
175 impl<'cx, 'tcx> Iterator for Elaborator<'cx, 'tcx> {
176     type Item = ty::Predicate<'tcx>;
177
178     fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
179         // Extract next item from top-most stack frame, if any.
180         let next_predicate = match self.stack.pop() {
181             Some(predicate) => predicate,
182             None => {
183                 // No more stack frames. Done.
184                 return None;
185             }
186         };
187         self.push(&next_predicate);
188         return Some(next_predicate);
189     }
190 }
191
192 ///////////////////////////////////////////////////////////////////////////
193 // Supertrait iterator
194 ///////////////////////////////////////////////////////////////////////////
195
196 pub type Supertraits<'cx, 'tcx> = FilterToTraits<Elaborator<'cx, 'tcx>>;
197
198 pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
199                               trait_ref: ty::PolyTraitRef<'tcx>)
200                               -> Supertraits<'cx, 'tcx>
201 {
202     elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
203 }
204
205 pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
206                                     bounds: &[ty::PolyTraitRef<'tcx>])
207                                     -> Supertraits<'cx, 'tcx>
208 {
209     elaborate_trait_refs(tcx, bounds).filter_to_traits()
210 }
211
212 ///////////////////////////////////////////////////////////////////////////
213 // Iterator over def-ids of supertraits
214
215 pub struct SupertraitDefIds<'cx, 'tcx:'cx> {
216     tcx: &'cx ty::ctxt<'tcx>,
217     stack: Vec<ast::DefId>,
218     visited: FnvHashSet<ast::DefId>,
219 }
220
221 pub fn supertrait_def_ids<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
222                                      trait_def_id: ast::DefId)
223                                      -> SupertraitDefIds<'cx, 'tcx>
224 {
225     SupertraitDefIds {
226         tcx: tcx,
227         stack: vec![trait_def_id],
228         visited: Some(trait_def_id).into_iter().collect(),
229     }
230 }
231
232 impl<'cx, 'tcx> Iterator for SupertraitDefIds<'cx, 'tcx> {
233     type Item = ast::DefId;
234
235     fn next(&mut self) -> Option<ast::DefId> {
236         let def_id = match self.stack.pop() {
237             Some(def_id) => def_id,
238             None => { return None; }
239         };
240
241         let predicates = ty::lookup_super_predicates(self.tcx, def_id);
242         let visited = &mut self.visited;
243         self.stack.extend(
244             predicates.predicates
245                       .iter()
246                       .filter_map(|p| p.to_opt_poly_trait_ref())
247                       .map(|t| t.def_id())
248                       .filter(|&super_def_id| visited.insert(super_def_id)));
249         Some(def_id)
250     }
251 }
252
253 ///////////////////////////////////////////////////////////////////////////
254 // Other
255 ///////////////////////////////////////////////////////////////////////////
256
257 /// A filter around an iterator of predicates that makes it yield up
258 /// just trait references.
259 pub struct FilterToTraits<I> {
260     base_iterator: I
261 }
262
263 impl<I> FilterToTraits<I> {
264     fn new(base: I) -> FilterToTraits<I> {
265         FilterToTraits { base_iterator: base }
266     }
267 }
268
269 impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
270     type Item = ty::PolyTraitRef<'tcx>;
271
272     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
273         loop {
274             match self.base_iterator.next() {
275                 None => {
276                     return None;
277                 }
278                 Some(ty::Predicate::Trait(data)) => {
279                     return Some(data.to_poly_trait_ref());
280                 }
281                 Some(_) => {
282                 }
283             }
284         }
285     }
286 }
287
288 ///////////////////////////////////////////////////////////////////////////
289 // Other
290 ///////////////////////////////////////////////////////////////////////////
291
292 // determine the `self` type, using fresh variables for all variables
293 // declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
294 // would return ($0, $1) where $0 and $1 are freshly instantiated type
295 // variables.
296 pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
297                                           span: Span,
298                                           impl_def_id: ast::DefId)
299                                           -> Substs<'tcx>
300 {
301     let tcx = infcx.tcx;
302     let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
303     infcx.fresh_substs_for_generics(span, &impl_generics)
304 }
305
306 impl<'tcx, N> fmt::Debug for VtableImplData<'tcx, N> {
307     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
308         write!(f, "VtableImpl({:?})", self.impl_def_id)
309     }
310 }
311
312 impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> {
313     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
314         write!(f, "VtableObject(...)")
315     }
316 }
317
318 /// See `super::obligations_for_generics`
319 pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
320                                      cause: ObligationCause<'tcx>,
321                                      recursion_depth: usize,
322                                      generic_bounds: &ty::InstantiatedPredicates<'tcx>)
323                                      -> VecPerParamSpace<PredicateObligation<'tcx>>
324 {
325     debug!("predicates_for_generics(generic_bounds={})",
326            generic_bounds.repr(tcx));
327
328     generic_bounds.predicates.map(|predicate| {
329         Obligation { cause: cause.clone(),
330                      recursion_depth: recursion_depth,
331                      predicate: predicate.clone() }
332     })
333 }
334
335 pub fn trait_ref_for_builtin_bound<'tcx>(
336     tcx: &ty::ctxt<'tcx>,
337     builtin_bound: ty::BuiltinBound,
338     param_ty: Ty<'tcx>)
339     -> Result<Rc<ty::TraitRef<'tcx>>, ErrorReported>
340 {
341     match tcx.lang_items.from_builtin_kind(builtin_bound) {
342         Ok(def_id) => {
343             Ok(Rc::new(ty::TraitRef {
344                 def_id: def_id,
345                 substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
346             }))
347         }
348         Err(e) => {
349             tcx.sess.err(&e);
350             Err(ErrorReported)
351         }
352     }
353 }
354
355
356 pub fn predicate_for_trait_ref<'tcx>(
357     cause: ObligationCause<'tcx>,
358     trait_ref: Rc<ty::TraitRef<'tcx>>,
359     recursion_depth: usize)
360     -> Result<PredicateObligation<'tcx>, ErrorReported>
361 {
362     Ok(Obligation {
363         cause: cause,
364         recursion_depth: recursion_depth,
365         predicate: trait_ref.as_predicate(),
366     })
367 }
368
369 pub fn predicate_for_trait_def<'tcx>(
370     tcx: &ty::ctxt<'tcx>,
371     cause: ObligationCause<'tcx>,
372     trait_def_id: ast::DefId,
373     recursion_depth: usize,
374     param_ty: Ty<'tcx>)
375     -> Result<PredicateObligation<'tcx>, ErrorReported>
376 {
377     let trait_ref = Rc::new(ty::TraitRef {
378         def_id: trait_def_id,
379         substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
380     });
381     predicate_for_trait_ref(cause, trait_ref, recursion_depth)
382 }
383
384 pub fn predicate_for_builtin_bound<'tcx>(
385     tcx: &ty::ctxt<'tcx>,
386     cause: ObligationCause<'tcx>,
387     builtin_bound: ty::BuiltinBound,
388     recursion_depth: usize,
389     param_ty: Ty<'tcx>)
390     -> Result<PredicateObligation<'tcx>, ErrorReported>
391 {
392     let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
393     predicate_for_trait_ref(cause, trait_ref, recursion_depth)
394 }
395
396 /// Cast a trait reference into a reference to one of its super
397 /// traits; returns `None` if `target_trait_def_id` is not a
398 /// supertrait.
399 pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
400                     source_trait_ref: ty::PolyTraitRef<'tcx>,
401                     target_trait_def_id: ast::DefId)
402                     -> Vec<ty::PolyTraitRef<'tcx>>
403 {
404     if source_trait_ref.def_id() == target_trait_def_id {
405         return vec![source_trait_ref]; // shorcut the most common case
406     }
407
408     supertraits(tcx, source_trait_ref)
409         .filter(|r| r.def_id() == target_trait_def_id)
410         .collect()
411 }
412
413 /// Given an object of type `object_trait_ref`, returns the index of
414 /// the method `n_method` found in the trait `trait_def_id` (which
415 /// should be a supertrait of `object_trait_ref`) within the vtable
416 /// for `object_trait_ref`.
417 pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
418                                                object_trait_ref: ty::PolyTraitRef<'tcx>,
419                                                trait_def_id: ast::DefId,
420                                                method_offset_in_trait: usize) -> usize {
421     // We need to figure the "real index" of the method in a
422     // listing of all the methods of an object. We do this by
423     // iterating down the supertraits of the object's trait until
424     // we find the trait the method came from, counting up the
425     // methods from them.
426     let mut method_count = 0;
427
428     for bound_ref in transitive_bounds(tcx, &[object_trait_ref]) {
429         if bound_ref.def_id() == trait_def_id {
430             break;
431         }
432
433         let trait_items = ty::trait_items(tcx, bound_ref.def_id());
434         for trait_item in &**trait_items {
435             match *trait_item {
436                 ty::MethodTraitItem(_) => method_count += 1,
437                 ty::TypeTraitItem(_) => {}
438             }
439         }
440     }
441
442     // count number of methods preceding the one we are selecting and
443     // add them to the total offset; skip over associated types.
444     let trait_items = ty::trait_items(tcx, trait_def_id);
445     for trait_item in trait_items.iter().take(method_offset_in_trait) {
446         match *trait_item {
447             ty::MethodTraitItem(_) => method_count += 1,
448             ty::TypeTraitItem(_) => {}
449         }
450     }
451
452     // the item at the offset we were given really ought to be a method
453     assert!(match trait_items[method_offset_in_trait] {
454         ty::MethodTraitItem(_) => true,
455         ty::TypeTraitItem(_) => false
456     });
457
458     method_count
459 }
460
461 pub enum TupleArgumentsFlag { Yes, No }
462
463 pub fn closure_trait_ref_and_return_type<'tcx>(
464     tcx: &ty::ctxt<'tcx>,
465     fn_trait_def_id: ast::DefId,
466     self_ty: Ty<'tcx>,
467     sig: &ty::PolyFnSig<'tcx>,
468     tuple_arguments: TupleArgumentsFlag)
469     -> ty::Binder<(Rc<ty::TraitRef<'tcx>>, Ty<'tcx>)>
470 {
471     let arguments_tuple = match tuple_arguments {
472         TupleArgumentsFlag::No => sig.0.inputs[0],
473         TupleArgumentsFlag::Yes => ty::mk_tup(tcx, sig.0.inputs.to_vec()),
474     };
475     let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty);
476     let trait_ref = Rc::new(ty::TraitRef {
477         def_id: fn_trait_def_id,
478         substs: tcx.mk_substs(trait_substs),
479     });
480     ty::Binder((trait_ref, sig.0.output.unwrap_or(ty::mk_nil(tcx))))
481 }
482
483 impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
484     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
485         format!("Obligation(predicate={},depth={})",
486                 self.predicate.repr(tcx),
487                 self.recursion_depth)
488     }
489 }
490
491 impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
492     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
493         match *self {
494             super::VtableImpl(ref v) =>
495                 v.repr(tcx),
496
497             super::VtableDefaultImpl(ref t) =>
498                 t.repr(tcx),
499
500             super::VtableClosure(ref d, ref s) =>
501                 format!("VtableClosure({},{})",
502                         d.repr(tcx),
503                         s.repr(tcx)),
504
505             super::VtableFnPointer(ref d) =>
506                 format!("VtableFnPointer({})",
507                         d.repr(tcx)),
508
509             super::VtableObject(ref d) =>
510                 format!("VtableObject({})",
511                         d.repr(tcx)),
512
513             super::VtableParam(ref n) =>
514                 format!("VtableParam({})",
515                         n.repr(tcx)),
516
517             super::VtableBuiltin(ref d) =>
518                 d.repr(tcx)
519         }
520     }
521 }
522
523 impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableImplData<'tcx, N> {
524     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
525         format!("VtableImpl(impl_def_id={}, substs={}, nested={})",
526                 self.impl_def_id.repr(tcx),
527                 self.substs.repr(tcx),
528                 self.nested.repr(tcx))
529     }
530 }
531
532 impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
533     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
534         format!("VtableBuiltin(nested={})",
535                 self.nested.repr(tcx))
536     }
537 }
538
539 impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultImplData<N> {
540     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
541         format!("VtableDefaultImplData(trait_def_id={}, nested={})",
542                 self.trait_def_id.repr(tcx),
543                 self.nested.repr(tcx))
544     }
545 }
546
547 impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
548     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
549         format!("VtableObject(object_ty={})",
550                 self.object_ty.repr(tcx))
551     }
552 }
553
554 impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
555     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
556         match *self {
557             super::Unimplemented =>
558                 format!("Unimplemented"),
559
560             super::OutputTypeParameterMismatch(ref a, ref b, ref c) =>
561                 format!("OutputTypeParameterMismatch({},{},{})",
562                         a.repr(tcx),
563                         b.repr(tcx),
564                         c.repr(tcx)),
565         }
566     }
567 }
568
569 impl<'tcx> Repr<'tcx> for super::FulfillmentError<'tcx> {
570     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
571         format!("FulfillmentError({},{})",
572                 self.obligation.repr(tcx),
573                 self.code.repr(tcx))
574     }
575 }
576
577 impl<'tcx> Repr<'tcx> for super::FulfillmentErrorCode<'tcx> {
578     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
579         match *self {
580             super::CodeSelectionError(ref o) => o.repr(tcx),
581             super::CodeProjectionError(ref o) => o.repr(tcx),
582             super::CodeAmbiguity => format!("Ambiguity")
583         }
584     }
585 }
586
587 impl<'tcx> fmt::Debug for super::FulfillmentErrorCode<'tcx> {
588     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
589         match *self {
590             super::CodeSelectionError(ref e) => write!(f, "{:?}", e),
591             super::CodeProjectionError(ref e) => write!(f, "{:?}", e),
592             super::CodeAmbiguity => write!(f, "Ambiguity")
593         }
594     }
595 }
596
597 impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> {
598     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
599         self.err.repr(tcx)
600     }
601 }
602
603 impl<'tcx> fmt::Debug for super::MismatchedProjectionTypes<'tcx> {
604     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
605         write!(f, "MismatchedProjectionTypes(..)")
606     }
607 }