@@ -1105,6 +1105,23 @@ pub struct TyTrait {
1105
1105
pub bounds : ExistentialBounds
1106
1106
}
1107
1107
1108
+ /**
1109
+ * A complete reference to a trait. These take numerous guises in syntax,
1110
+ * but perhaps the most recognizable form is in a where clause:
1111
+ *
1112
+ * T : Foo<U>
1113
+ *
1114
+ * This would be represented by a trait-reference where the def-id is the
1115
+ * def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
1116
+ * `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
1117
+ *
1118
+ * Trait references also appear in object types like `Foo<U>`, but in
1119
+ * that case the `Self` parameter is absent from the substitutions.
1120
+ *
1121
+ * Note that a `TraitRef` introduces a level of region binding, to
1122
+ * account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
1123
+ * U>` or higher-ranked object types.
1124
+ */
1108
1125
#[ deriving( Clone , PartialEq , Eq , Hash , Show ) ]
1109
1126
pub struct TraitRef {
1110
1127
pub def_id : DefId ,
@@ -1410,6 +1427,14 @@ impl TraitRef {
1410
1427
// associated types.
1411
1428
self . substs . types . as_slice ( )
1412
1429
}
1430
+
1431
+ pub fn has_escaping_regions ( & self ) -> bool {
1432
+ self . substs . has_regions_escaping_depth ( 1 )
1433
+ }
1434
+
1435
+ pub fn has_bound_regions ( & self ) -> bool {
1436
+ self . substs . has_regions_escaping_depth ( 0 )
1437
+ }
1413
1438
}
1414
1439
1415
1440
/// When type checking, we use the `ParameterEnvironment` to track
@@ -1826,7 +1851,10 @@ impl FlagComputation {
1826
1851
}
1827
1852
1828
1853
& ty_trait( box TyTrait { ref principal, ref bounds } ) => {
1829
- self . add_substs ( & principal. substs ) ;
1854
+ let mut computation = FlagComputation :: new ( ) ;
1855
+ computation. add_substs ( & principal. substs ) ;
1856
+ self . add_bound_computation ( & computation) ;
1857
+
1830
1858
self . add_bounds ( bounds) ;
1831
1859
}
1832
1860
@@ -4708,9 +4736,99 @@ pub fn bounds_for_trait_ref(tcx: &ctxt,
4708
4736
-> ty:: ParamBounds
4709
4737
{
4710
4738
let trait_def = lookup_trait_def ( tcx, trait_ref. def_id ) ;
4739
+
4711
4740
debug ! ( "bounds_for_trait_ref(trait_def={}, trait_ref={})" ,
4712
4741
trait_def. repr( tcx) , trait_ref. repr( tcx) ) ;
4713
- trait_def. bounds . subst ( tcx, & trait_ref. substs )
4742
+
4743
+ // The interaction between HRTB and supertraits is not entirely
4744
+ // obvious. Let me walk you (and myself) through an example.
4745
+ //
4746
+ // Let's start with an easy case. Consider two traits:
4747
+ //
4748
+ // trait Foo<'a> : Bar<'a,'a> { }
4749
+ // trait Bar<'b,'c> { }
4750
+ //
4751
+ // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then
4752
+ // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we
4753
+ // knew that `Foo<'x>` (for any 'x) then we also know that
4754
+ // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
4755
+ // normal substitution.
4756
+ //
4757
+ // In terms of why this is sound, the idea is that whenever there
4758
+ // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
4759
+ // holds. So if there is an impl of `T:Foo<'a>` that applies to
4760
+ // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
4761
+ // `'a`.
4762
+ //
4763
+ // Another example to be careful of is this:
4764
+ //
4765
+ // trait Foo1<'a> : for<'b> Bar1<'a,'b> { }
4766
+ // trait Bar1<'b,'c> { }
4767
+ //
4768
+ // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know?
4769
+ // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The
4770
+ // reason is similar to the previous example: any impl of
4771
+ // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So
4772
+ // basically we would want to collapse the bound lifetimes from
4773
+ // the input (`trait_ref`) and the supertraits.
4774
+ //
4775
+ // To achieve this in practice is fairly straightforward. Let's
4776
+ // consider the more complicated scenario:
4777
+ //
4778
+ // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x`
4779
+ // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`,
4780
+ // where both `'x` and `'b` would have a DB index of 1.
4781
+ // The substitution from the input trait-ref is therefore going to be
4782
+ // `'a => 'x` (where `'x` has a DB index of 1).
4783
+ // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
4784
+ // early-bound parameter and `'b' is a late-bound parameter with a
4785
+ // DB index of 1.
4786
+ // - If we replace `'a` with `'x` from the input, it too will have
4787
+ // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
4788
+ // just as we wanted.
4789
+ //
4790
+ // There is only one catch. If we just apply the substitution `'a
4791
+ // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
4792
+ // adjust the DB index because we substituting into a binder (it
4793
+ // tries to be so smart...) resulting in `for<'x> for<'b>
4794
+ // Bar1<'x,'b>` (we have no syntax for this, so use your
4795
+ // imagination). Basically the 'x will have DB index of 2 and 'b
4796
+ // will have DB index of 1. Not quite what we want. So we apply
4797
+ // the substitution to the *contents* of the trait reference,
4798
+ // rather than the trait reference itself (put another way, the
4799
+ // substitution code expects equal binding levels in the values
4800
+ // from the substitution and the value being substituted into, and
4801
+ // this trick achieves that).
4802
+
4803
+ // Carefully avoid the binder introduced by each trait-ref by
4804
+ // substituting over the substs, not the trait-refs themselves,
4805
+ // thus achieving the "collapse" described in the big comment
4806
+ // above.
4807
+ let trait_bounds: Vec < _ > =
4808
+ trait_def. bounds . trait_bounds
4809
+ . iter ( )
4810
+ . map ( |bound_trait_ref| {
4811
+ ty:: TraitRef :: new ( bound_trait_ref. def_id ,
4812
+ bound_trait_ref. substs . subst ( tcx, & trait_ref. substs ) )
4813
+ } )
4814
+ . map ( |bound_trait_ref| Rc :: new ( bound_trait_ref) )
4815
+ . collect ( ) ;
4816
+
4817
+ debug ! ( "bounds_for_trait_ref: trait_bounds={}" ,
4818
+ trait_bounds. repr( tcx) ) ;
4819
+
4820
+ // The region bounds and builtin bounds do not currently introduce
4821
+ // binders so we can just substitute in a straightforward way here.
4822
+ let region_bounds =
4823
+ trait_def. bounds . region_bounds . subst ( tcx, & trait_ref. substs ) ;
4824
+ let builtin_bounds =
4825
+ trait_def. bounds . builtin_bounds . subst ( tcx, & trait_ref. substs ) ;
4826
+
4827
+ ty:: ParamBounds {
4828
+ trait_bounds : trait_bounds,
4829
+ region_bounds : region_bounds,
4830
+ builtin_bounds : builtin_bounds,
4831
+ }
4714
4832
}
4715
4833
4716
4834
/// Iterate over attributes of a definition.
0 commit comments