Skip to content

Commit 22fc7d6

Browse files
committed
Point to where clause for GATs
1 parent 2fc3c69 commit 22fc7d6

File tree

7 files changed

+200
-8
lines changed

7 files changed

+200
-8
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+94-4
Original file line numberDiff line numberDiff line change
@@ -2259,9 +2259,99 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
22592259
}
22602260
};
22612261

2262-
let mut err = match *sub {
2263-
ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. })
2264-
| ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }) => {
2262+
#[derive(Debug)]
2263+
enum SubOrigin<'hir> {
2264+
GAT(&'hir hir::Generics<'hir>),
2265+
Impl(&'hir hir::Generics<'hir>),
2266+
Trait(&'hir hir::Generics<'hir>),
2267+
Fn(&'hir hir::Generics<'hir>),
2268+
Unknown,
2269+
}
2270+
let sub_origin = 'origin: {
2271+
match *sub {
2272+
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => {
2273+
let node = self.tcx.hir().get_if_local(def_id).unwrap();
2274+
match node {
2275+
Node::GenericParam(param) => {
2276+
for h in self.tcx.hir().parent_iter(param.hir_id) {
2277+
break 'origin match h.1 {
2278+
Node::ImplItem(hir::ImplItem {
2279+
kind: hir::ImplItemKind::TyAlias(..),
2280+
generics,
2281+
..
2282+
}) => SubOrigin::GAT(generics),
2283+
Node::ImplItem(hir::ImplItem {
2284+
kind: hir::ImplItemKind::Fn(..),
2285+
generics,
2286+
..
2287+
}) => SubOrigin::Fn(generics),
2288+
Node::TraitItem(hir::TraitItem {
2289+
kind: hir::TraitItemKind::Type(..),
2290+
generics,
2291+
..
2292+
}) => SubOrigin::GAT(generics),
2293+
Node::TraitItem(hir::TraitItem {
2294+
kind: hir::TraitItemKind::Fn(..),
2295+
generics,
2296+
..
2297+
}) => SubOrigin::Fn(generics),
2298+
Node::Item(hir::Item {
2299+
kind: hir::ItemKind::Trait(_, _, generics, _, _),
2300+
..
2301+
}) => SubOrigin::Trait(generics),
2302+
Node::Item(hir::Item {
2303+
kind: hir::ItemKind::Impl(hir::Impl { generics, .. }),
2304+
..
2305+
}) => SubOrigin::Impl(generics),
2306+
Node::Item(hir::Item {
2307+
kind: hir::ItemKind::Fn(_, generics, _),
2308+
..
2309+
}) => SubOrigin::Fn(generics),
2310+
_ => continue,
2311+
};
2312+
}
2313+
}
2314+
_ => {}
2315+
}
2316+
}
2317+
_ => {}
2318+
}
2319+
SubOrigin::Unknown
2320+
};
2321+
debug!(?sub_origin);
2322+
2323+
let mut err = match (*sub, sub_origin) {
2324+
// In the case of GATs, we have to be careful. If we a type parameter `T` on an impl,
2325+
// but a lifetime `'a` on an associated type, then we might need to suggest adding
2326+
// `where T: 'a`. Importantly, this is on the GAT span, not on the `T` declaration.
2327+
(ty::ReEarlyBound(ty::EarlyBoundRegion { name: _, .. }), SubOrigin::GAT(generics)) => {
2328+
// Does the required lifetime have a nice name we can print?
2329+
let mut err = struct_span_err!(
2330+
self.tcx.sess,
2331+
span,
2332+
E0309,
2333+
"{} may not live long enough",
2334+
labeled_user_string
2335+
);
2336+
let pred = format!("{}: {}", bound_kind, sub);
2337+
let suggestion = format!(
2338+
"{} {}",
2339+
if !generics.where_clause.predicates.is_empty() { "," } else { " where" },
2340+
pred,
2341+
);
2342+
err.span_suggestion(
2343+
generics.where_clause.tail_span_for_suggestion(),
2344+
"consider adding a where clause".into(),
2345+
suggestion,
2346+
Applicability::MaybeIncorrect,
2347+
);
2348+
err
2349+
}
2350+
(
2351+
ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. })
2352+
| ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }),
2353+
_,
2354+
) => {
22652355
// Does the required lifetime have a nice name we can print?
22662356
let mut err = struct_span_err!(
22672357
self.tcx.sess,
@@ -2278,7 +2368,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
22782368
err
22792369
}
22802370

2281-
ty::ReStatic => {
2371+
(ty::ReStatic, _) => {
22822372
// Does the required lifetime have a nice name we can print?
22832373
let mut err = struct_span_err!(
22842374
self.tcx.sess,

compiler/rustc_infer/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#![feature(in_band_lifetimes)]
2323
#![feature(control_flow_enum)]
2424
#![feature(min_specialization)]
25+
#![feature(label_break_value)]
2526
#![recursion_limit = "512"] // For rustdoc
2627

2728
#[macro_use]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![feature(generic_associated_types)]
2+
// check-fail
3+
4+
trait StreamingIter {
5+
type Item<'a> where Self: 'a;
6+
fn next<'a>(&'a mut self) -> Option<Self::Item::<'a>>;
7+
}
8+
9+
struct StreamingSliceIter<'a, T> {
10+
idx: usize,
11+
data: &'a mut [T],
12+
}
13+
14+
impl<'b, T: 'b> StreamingIter for StreamingSliceIter<'b, T> {
15+
type Item<'a> = &'a mut T;
16+
//~^ the parameter type
17+
fn next(&mut self) -> Option<&mut T> {
18+
loop {}
19+
}
20+
}
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0309]: the parameter type `T` may not live long enough
2+
--> $DIR/issue-84931.rs:15:21
3+
|
4+
LL | type Item<'a> = &'a mut T;
5+
| - ^^^^^^^^^ ...so that the reference type `&'a mut T` does not outlive the data it points at
6+
| |
7+
| help: consider adding a where clause: `where T: 'a`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0309`.

src/test/ui/generic-associated-types/issue-86483.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,10 @@ LL | for<'a> T: 'a,
3737
error[E0309]: the parameter type `T` may not live long enough
3838
--> $DIR/issue-86483.rs:9:32
3939
|
40-
LL | pub trait IceIce<T>
41-
| - help: consider adding an explicit lifetime bound...: `T: 'v`
42-
...
4340
LL | type Ice<'v>: IntoIterator<Item = &'v T>;
44-
| ^^^^^^^^^^^^ ...so that the reference type `&'v T` does not outlive the data it points at
41+
| ^^^^^^^^^^^^ - help: consider adding a where clause: `where T: 'v`
42+
| |
43+
| ...so that the reference type `&'v T` does not outlive the data it points at
4544

4645
error: aborting due to 3 previous errors
4746

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#![feature(generic_associated_types)]
2+
// check-fail
3+
4+
enum Either<L, R> {
5+
Left(L),
6+
Right(R),
7+
}
8+
9+
pub trait HasChildrenOf {
10+
type T;
11+
type TRef<'a>;
12+
13+
fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>;
14+
fn take_children(self) -> Vec<Self::T>;
15+
}
16+
17+
impl<Left, Right> HasChildrenOf for Either<Left, Right>
18+
where
19+
Left: HasChildrenOf,
20+
Right: HasChildrenOf,
21+
{
22+
type T = Either<Left::T, Right::T>;
23+
type TRef<'a>
24+
//~^ the associated type
25+
//~^^ the associated type
26+
where
27+
<Left as HasChildrenOf>::T: 'a,
28+
<Right as HasChildrenOf>::T: 'a
29+
= Either<&'a Left::T, &'a Right::T>;
30+
31+
fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>> {
32+
todo!()
33+
}
34+
35+
fn take_children(self) -> Vec<Self::T> {
36+
todo!()
37+
}
38+
}
39+
40+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0309]: the associated type `<Left as HasChildrenOf>::T` may not live long enough
2+
--> $DIR/issue-86787.rs:23:5
3+
|
4+
LL | / type TRef<'a>
5+
LL | |
6+
LL | |
7+
LL | | where
8+
LL | | <Left as HasChildrenOf>::T: 'a,
9+
LL | | <Right as HasChildrenOf>::T: 'a
10+
| | - help: consider adding a where clause: `, <Left as HasChildrenOf>::T: 'a`
11+
LL | | = Either<&'a Left::T, &'a Right::T>;
12+
| |________________________________________^ ...so that the type `<Left as HasChildrenOf>::T` will meet its required lifetime bounds
13+
14+
error[E0309]: the associated type `<Right as HasChildrenOf>::T` may not live long enough
15+
--> $DIR/issue-86787.rs:23:5
16+
|
17+
LL | / type TRef<'a>
18+
LL | |
19+
LL | |
20+
LL | | where
21+
LL | | <Left as HasChildrenOf>::T: 'a,
22+
LL | | <Right as HasChildrenOf>::T: 'a
23+
| | - help: consider adding a where clause: `, <Right as HasChildrenOf>::T: 'a`
24+
LL | | = Either<&'a Left::T, &'a Right::T>;
25+
| |________________________________________^ ...so that the type `<Right as HasChildrenOf>::T` will meet its required lifetime bounds
26+
27+
error: aborting due to 2 previous errors
28+
29+
For more information about this error, try `rustc --explain E0309`.

0 commit comments

Comments
 (0)