fix handling of Self
This commit is contained in:
parent
ad9986605f
commit
706e52e2cc
5 changed files with 79 additions and 26 deletions
|
|
@ -794,7 +794,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
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 let Some(type_param) = generics.type_param(param, self.tcx) {
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -713,6 +713,13 @@ impl ty::EarlyBoundRegion {
|
|||
|
||||
/// 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>,
|
||||
|
|
@ -755,18 +762,34 @@ impl<'a, 'gcx, 'tcx> Generics {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the `TypeParameterDef` associated with this `ParamTy`, or `None`
|
||||
/// if `param` is `self`.
|
||||
/// Returns the `TypeParameterDef` associated with this `ParamTy`.
|
||||
pub fn type_param(&'tcx self,
|
||||
param: &ParamTy,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
||||
-> Option<&TypeParameterDef> {
|
||||
-> &TypeParameterDef {
|
||||
if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
|
||||
let type_param_start = (self.has_self as usize) + self.regions.len();
|
||||
if let Some(idx) = (idx as usize).checked_sub(type_param_start) {
|
||||
Some(&self.types[idx])
|
||||
// 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 {
|
||||
None
|
||||
assert!(self.has_self && idx == 0);
|
||||
&self.types[0]
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
|
||||
|
|
|
|||
|
|
@ -519,9 +519,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
} else if let Some(&ty::TyS {
|
||||
sty: ty::TypeVariants::TyParam(ref pt), ..
|
||||
}) = k.as_type() {
|
||||
!impl_generics.type_param(pt, self)
|
||||
.expect("drop impl param doesn't have a ParameterDef?")
|
||||
.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.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,11 @@ struct Foo<T> {
|
|||
foo: &'static T
|
||||
}
|
||||
|
||||
trait X<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> {
|
||||
|
|
|
|||
|
|
@ -27,37 +27,64 @@ note: ...so that the reference type `&'static T` does not outlive the data it po
|
|||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0309]: the parameter type `K` may not live long enough
|
||||
--> $DIR/lifetime-doesnt-live-long-enough.rs:35:5
|
||||
--> $DIR/lifetime-doesnt-live-long-enough.rs:32:5
|
||||
|
|
||||
34 | impl<K> Nested<K> {
|
||||
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`...
|
||||
35 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
|
||||
36 | | }
|
||||
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:35:5
|
||||
--> $DIR/lifetime-doesnt-live-long-enough.rs:39:5
|
||||
|
|
||||
35 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
|
||||
36 | | }
|
||||
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:37:5
|
||||
--> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
|
||||
|
|
||||
37 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
|
||||
41 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
|
||||
| ^ -- help: consider adding an explicit lifetime bound `M: 'a`...
|
||||
| _____|
|
||||
| |
|
||||
38 | | }
|
||||
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:37:5
|
||||
--> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
|
||||
|
|
||||
37 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
|
||||
38 | | }
|
||||
41 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
|
||||
42 | | }
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue