Skip to content

Commit 0f0f5db

Browse files
committed
Auto merge of #44959 - arielb1:generic-errors, r=eddyb
handle nested generics in Generics::type_param/region_param Fixes #44952. r? @eddyb
2 parents 9ae6ed7 + 706e52e commit 0f0f5db

File tree

5 files changed

+133
-14
lines changed

5 files changed

+133
-14
lines changed

src/librustc/infer/error_reporting/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -794,8 +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 generics.types.len() > 0 {
798-
let type_param = generics.type_param(param);
797+
if !param.is_self() {
798+
let type_param = generics.type_param(param, self.tcx);
799799
let hir = &self.tcx.hir;
800800
hir.as_local_node_id(type_param.def_id).map(|id| {
801801
// Get the `hir::TyParam` to verify wether it already has any bounds.

src/librustc/ty/mod.rs

+54-9
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>,
@@ -729,7 +736,7 @@ pub struct Generics {
729736
pub has_late_bound_regions: Option<Span>,
730737
}
731738

732-
impl Generics {
739+
impl<'a, 'gcx, 'tcx> Generics {
733740
pub fn parent_count(&self) -> usize {
734741
self.parent_regions as usize + self.parent_types as usize
735742
}
@@ -742,14 +749,52 @@ impl Generics {
742749
self.parent_count() + self.own_count()
743750
}
744751

745-
pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef {
746-
assert_eq!(self.parent_count(), 0);
747-
&self.regions[param.index as usize - self.has_self as usize]
748-
}
749-
750-
pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef {
751-
assert_eq!(self.parent_count(), 0);
752-
&self.types[param.idx as usize - self.has_self as usize - self.regions.len()]
752+
pub fn region_param(&'tcx self,
753+
param: &EarlyBoundRegion,
754+
tcx: TyCtxt<'a, 'gcx, 'tcx>)
755+
-> &'tcx RegionParameterDef
756+
{
757+
if let Some(index) = param.index.checked_sub(self.parent_count() as u32) {
758+
&self.regions[index as usize - self.has_self as usize]
759+
} else {
760+
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
761+
.region_param(param, tcx)
762+
}
763+
}
764+
765+
/// Returns the `TypeParameterDef` associated with this `ParamTy`.
766+
pub fn type_param(&'tcx self,
767+
param: &ParamTy,
768+
tcx: TyCtxt<'a, 'gcx, 'tcx>)
769+
-> &TypeParameterDef {
770+
if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
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]
790+
} else {
791+
assert!(self.has_self && idx == 0);
792+
&self.types[0]
793+
}
794+
} else {
795+
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
796+
.type_param(param, tcx)
797+
}
753798
}
754799
}
755800

src/librustc/ty/util.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
515515
let result = item_substs.iter().zip(impl_substs.iter())
516516
.filter(|&(_, &k)| {
517517
if let Some(&ty::RegionKind::ReEarlyBound(ref ebr)) = k.as_region() {
518-
!impl_generics.region_param(ebr).pure_wrt_drop
518+
!impl_generics.region_param(ebr, self).pure_wrt_drop
519519
} else if let Some(&ty::TyS {
520520
sty: ty::TypeVariants::TyParam(ref pt), ..
521521
}) = k.as_type() {
522-
!impl_generics.type_param(pt).pure_wrt_drop
522+
!impl_generics.type_param(pt, self).pure_wrt_drop
523523
} else {
524524
// not a type or region param - this should be reported
525525
// as an error.

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

+14
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,18 @@ struct Foo<T> {
2828
foo: &'static T
2929
}
3030

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+
}
36+
37+
struct Nested<K>(K);
38+
impl<K> Nested<K> {
39+
fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
40+
}
41+
fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
42+
}
43+
}
44+
3145
fn main() {}

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

+61-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,65 @@ note: ...so that the reference type `&'static T` does not outlive the data it po
2626
28 | foo: &'static T
2727
| ^^^^^^^^^^^^^^^
2828

29-
error: aborting due to 2 previous errors
29+
error[E0309]: the parameter type `K` may not live long enough
30+
--> $DIR/lifetime-doesnt-live-long-enough.rs:32:5
31+
|
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> {
60+
| - help: consider adding an explicit lifetime bound `K: 'a`...
61+
39 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
62+
40 | | }
63+
| |_____^
64+
|
65+
note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
66+
--> $DIR/lifetime-doesnt-live-long-enough.rs:39:5
67+
|
68+
39 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
69+
40 | | }
70+
| |_____^
71+
72+
error[E0309]: the parameter type `M` may not live long enough
73+
--> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
74+
|
75+
41 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
76+
| ^ -- help: consider adding an explicit lifetime bound `M: 'a`...
77+
| _____|
78+
| |
79+
42 | | }
80+
| |_____^
81+
|
82+
note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
83+
--> $DIR/lifetime-doesnt-live-long-enough.rs:41:5
84+
|
85+
41 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
86+
42 | | }
87+
| |_____^
88+
89+
error: aborting due to 6 previous errors
3090

0 commit comments

Comments
 (0)