let generics = self.tcx.generics_of(did);
// Account for the case where `did` corresponds to `Self`, which doesn't have
// the expected type argument.
- if generics.types.len() > 0 {
- let type_param = generics.type_param(param);
+ if !param.is_self() {
+ let type_param = generics.type_param(param, self.tcx);
let hir = &self.tcx.hir;
hir.as_local_node_id(type_param.def_id).map(|id| {
// Get the `hir::TyParam` to verify wether it already has any bounds.
/// Information about the formal type/lifetime parameters associated
/// with an item or method. Analogous to hir::Generics.
+///
+/// Note that in the presence of a `Self` parameter, the ordering here
+/// is different from the ordering in a Substs. Substs are ordered as
+/// Self, *Regions, *Other Type Params, (...child generics)
+/// while this struct is ordered as
+/// regions = Regions
+/// types = [Self, *Other Type Params]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Generics {
pub parent: Option<DefId>,
pub has_late_bound_regions: Option<Span>,
}
-impl Generics {
+impl<'a, 'gcx, 'tcx> Generics {
pub fn parent_count(&self) -> usize {
self.parent_regions as usize + self.parent_types as usize
}
self.parent_count() + self.own_count()
}
- pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef {
- assert_eq!(self.parent_count(), 0);
- &self.regions[param.index as usize - self.has_self as usize]
- }
-
- pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef {
- assert_eq!(self.parent_count(), 0);
- &self.types[param.idx as usize - self.has_self as usize - self.regions.len()]
+ pub fn region_param(&'tcx self,
+ param: &EarlyBoundRegion,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>)
+ -> &'tcx RegionParameterDef
+ {
+ if let Some(index) = param.index.checked_sub(self.parent_count() as u32) {
+ &self.regions[index as usize - self.has_self as usize]
+ } else {
+ tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
+ .region_param(param, tcx)
+ }
+ }
+
+ /// Returns the `TypeParameterDef` associated with this `ParamTy`.
+ pub fn type_param(&'tcx self,
+ param: &ParamTy,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>)
+ -> &TypeParameterDef {
+ if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
+ // non-Self type parameters are always offset by exactly
+ // `self.regions.len()`. In the absence of a Self, this is obvious,
+ // but even in the absence of a `Self` we just have to "compensate"
+ // for the regions:
+ //
+ // For example, for `trait Foo<'a, 'b, T1, T2>`, the
+ // situation is:
+ // Substs:
+ // 0 1 2 3 4
+ // Self 'a 'b T1 T2
+ // generics.types:
+ // 0 1 2
+ // Self T1 T2
+ // And it can be seen that to move from a substs offset to a
+ // generics offset you just have to offset by the number of regions.
+ let type_param_offset = self.regions.len();
+ if let Some(idx) = (idx as usize).checked_sub(type_param_offset) {
+ assert!(!(self.has_self && idx == 0));
+ &self.types[idx]
+ } else {
+ assert!(self.has_self && idx == 0);
+ &self.types[0]
+ }
+ } else {
+ tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
+ .type_param(param, tcx)
+ }
}
}
let result = item_substs.iter().zip(impl_substs.iter())
.filter(|&(_, &k)| {
if let Some(&ty::RegionKind::ReEarlyBound(ref ebr)) = k.as_region() {
- !impl_generics.region_param(ebr).pure_wrt_drop
+ !impl_generics.region_param(ebr, self).pure_wrt_drop
} else if let Some(&ty::TyS {
sty: ty::TypeVariants::TyParam(ref pt), ..
}) = k.as_type() {
- !impl_generics.type_param(pt).pure_wrt_drop
+ !impl_generics.type_param(pt, self).pure_wrt_drop
} else {
// not a type or region param - this should be reported
// as an error.
foo: &'static T
}
+trait X<K>: Sized {
+ fn foo<'a, L: X<&'a Nested<K>>>();
+ // check that we give a sane error for `Self`
+ fn bar<'a, L: X<&'a Nested<Self>>>();
+}
+
+struct Nested<K>(K);
+impl<K> Nested<K> {
+ fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
+ }
+ fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
+ }
+}
+
fn main() {}
28 | foo: &'static T
| ^^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error[E0309]: the parameter type `K` may not live long enough
+ --> $DIR/lifetime-doesnt-live-long-enough.rs:32:5
+ |
+31 | trait X<K>: Sized {
+ | - help: consider adding an explicit lifetime bound `K: 'a`...
+32 | fn foo<'a, L: X<&'a Nested<K>>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
+ --> $DIR/lifetime-doesnt-live-long-enough.rs:32:5
+ |
+32 | fn foo<'a, L: X<&'a Nested<K>>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `Self` may not live long enough
+ --> $DIR/lifetime-doesnt-live-long-enough.rs:34:5
+ |
+34 | fn bar<'a, L: X<&'a Nested<Self>>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `Self: 'a`...
+note: ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
+ --> $DIR/lifetime-doesnt-live-long-enough.rs:34:5
+ |
+34 | fn bar<'a, L: X<&'a Nested<Self>>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `K` may not live long enough
+ --> $DIR/lifetime-doesnt-live-long-enough.rs:39:5
+ |
+38 | impl<K> Nested<K> {
+ | - help: consider adding an explicit lifetime bound `K: 'a`...
+39 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
+40 | | }
+ | |_____^
+ |
+note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
+ --> $DIR/lifetime-doesnt-live-long-enough.rs:39:5
+ |
+39 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
+40 | | }
+ | |_____^
+
+error[E0309]: the parameter type `M` may not live long enough
+ --> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
+ |
+41 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
+ | ^ -- help: consider adding an explicit lifetime bound `M: 'a`...
+ | _____|
+ | |
+42 | | }
+ | |_____^
+ |
+note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
+ --> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
+ |
+41 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
+42 | | }
+ | |_____^
+
+error: aborting due to 6 previous errors