Skip to content

Commit 706e52e

Browse files
committed
fix handling of Self
1 parent ad99866 commit 706e52e

File tree

5 files changed

+79
-26
lines changed

5 files changed

+79
-26
lines changed

src/librustc/infer/error_reporting/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
794794
let generics = self.tcx.generics_of(did);
795795
// Account for the case where `did` corresponds to `Self`, which doesn't have
796796
// the expected type argument.
797-
if let Some(type_param) = generics.type_param(param, self.tcx) {
797+
if !param.is_self() {
798+
let type_param = generics.type_param(param, self.tcx);
798799
let hir = &self.tcx.hir;
799800
hir.as_local_node_id(type_param.def_id).map(|id| {
800801
// Get the `hir::TyParam` to verify wether it already has any bounds.

src/librustc/ty/mod.rs

+30-7
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,13 @@ impl ty::EarlyBoundRegion {
713713

714714
/// Information about the formal type/lifetime parameters associated
715715
/// with an item or method. Analogous to hir::Generics.
716+
///
717+
/// Note that in the presence of a `Self` parameter, the ordering here
718+
/// is different from the ordering in a Substs. Substs are ordered as
719+
/// Self, *Regions, *Other Type Params, (...child generics)
720+
/// while this struct is ordered as
721+
/// regions = Regions
722+
/// types = [Self, *Other Type Params]
716723
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
717724
pub struct Generics {
718725
pub parent: Option<DefId>,
@@ -755,18 +762,34 @@ impl<'a, 'gcx, 'tcx> Generics {
755762
}
756763
}
757764

758-
/// Returns the `TypeParameterDef` associated with this `ParamTy`, or `None`
759-
/// if `param` is `self`.
765+
/// Returns the `TypeParameterDef` associated with this `ParamTy`.
760766
pub fn type_param(&'tcx self,
761767
param: &ParamTy,
762768
tcx: TyCtxt<'a, 'gcx, 'tcx>)
763-
-> Option<&TypeParameterDef> {
769+
-> &TypeParameterDef {
764770
if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
765-
let type_param_start = (self.has_self as usize) + self.regions.len();
766-
if let Some(idx) = (idx as usize).checked_sub(type_param_start) {
767-
Some(&self.types[idx])
771+
// non-Self type parameters are always offset by exactly
772+
// `self.regions.len()`. In the absence of a Self, this is obvious,
773+
// but even in the absence of a `Self` we just have to "compensate"
774+
// for the regions:
775+
//
776+
// For example, for `trait Foo<'a, 'b, T1, T2>`, the
777+
// situation is:
778+
// Substs:
779+
// 0 1 2 3 4
780+
// Self 'a 'b T1 T2
781+
// generics.types:
782+
// 0 1 2
783+
// Self T1 T2
784+
// And it can be seen that to move from a substs offset to a
785+
// generics offset you just have to offset by the number of regions.
786+
let type_param_offset = self.regions.len();
787+
if let Some(idx) = (idx as usize).checked_sub(type_param_offset) {
788+
assert!(!(self.has_self && idx == 0));
789+
&self.types[idx]
768790
} else {
769-
None
791+
assert!(self.has_self && idx == 0);
792+
&self.types[0]
770793
}
771794
} else {
772795
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))

src/librustc/ty/util.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -519,9 +519,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
519519
} else if let Some(&ty::TyS {
520520
sty: ty::TypeVariants::TyParam(ref pt), ..
521521
}) = k.as_type() {
522-
!impl_generics.type_param(pt, self)
523-
.expect("drop impl param doesn't have a ParameterDef?")
524-
.pure_wrt_drop
522+
!impl_generics.type_param(pt, self).pure_wrt_drop
525523
} else {
526524
// not a type or region param - this should be reported
527525
// as an error.

src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ struct Foo<T> {
2828
foo: &'static T
2929
}
3030

31-
trait X<T> {}
31+
trait X<K>: Sized {
32+
fn foo<'a, L: X<&'a Nested<K>>>();
33+
// check that we give a sane error for `Self`
34+
fn bar<'a, L: X<&'a Nested<Self>>>();
35+
}
3236

3337
struct Nested<K>(K);
3438
impl<K> Nested<K> {

src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr

+41-14
Original file line numberDiff line numberDiff line change
@@ -27,37 +27,64 @@ note: ...so that the reference type `&'static T` does not outlive the data it po
2727
| ^^^^^^^^^^^^^^^
2828

2929
error[E0309]: the parameter type `K` may not live long enough
30-
--> $DIR/lifetime-doesnt-live-long-enough.rs:35:5
30+
--> $DIR/lifetime-doesnt-live-long-enough.rs:32:5
3131
|
32-
34 | impl<K> Nested<K> {
32+
31 | trait X<K>: Sized {
33+
| - help: consider adding an explicit lifetime bound `K: 'a`...
34+
32 | fn foo<'a, L: X<&'a Nested<K>>>();
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
|
37+
note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
38+
--> $DIR/lifetime-doesnt-live-long-enough.rs:32:5
39+
|
40+
32 | fn foo<'a, L: X<&'a Nested<K>>>();
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
43+
error[E0309]: the parameter type `Self` may not live long enough
44+
--> $DIR/lifetime-doesnt-live-long-enough.rs:34:5
45+
|
46+
34 | fn bar<'a, L: X<&'a Nested<Self>>>();
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
48+
|
49+
= help: consider adding an explicit lifetime bound `Self: 'a`...
50+
note: ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
51+
--> $DIR/lifetime-doesnt-live-long-enough.rs:34:5
52+
|
53+
34 | fn bar<'a, L: X<&'a Nested<Self>>>();
54+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
55+
56+
error[E0309]: the parameter type `K` may not live long enough
57+
--> $DIR/lifetime-doesnt-live-long-enough.rs:39:5
58+
|
59+
38 | impl<K> Nested<K> {
3360
| - help: consider adding an explicit lifetime bound `K: 'a`...
34-
35 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
35-
36 | | }
61+
39 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
62+
40 | | }
3663
| |_____^
3764
|
3865
note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
39-
--> $DIR/lifetime-doesnt-live-long-enough.rs:35:5
66+
--> $DIR/lifetime-doesnt-live-long-enough.rs:39:5
4067
|
41-
35 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
42-
36 | | }
68+
39 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
69+
40 | | }
4370
| |_____^
4471

4572
error[E0309]: the parameter type `M` may not live long enough
46-
--> $DIR/lifetime-doesnt-live-long-enough.rs:37:5
73+
--> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
4774
|
48-
37 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
75+
41 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
4976
| ^ -- help: consider adding an explicit lifetime bound `M: 'a`...
5077
| _____|
5178
| |
52-
38 | | }
79+
42 | | }
5380
| |_____^
5481
|
5582
note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
56-
--> $DIR/lifetime-doesnt-live-long-enough.rs:37:5
83+
--> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
5784
|
58-
37 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
59-
38 | | }
85+
41 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
86+
42 | | }
6087
| |_____^
6188

62-
error: aborting due to 4 previous errors
89+
error: aborting due to 6 previous errors
6390

0 commit comments

Comments
 (0)