Skip to content

Commit b4f3232

Browse files
committed
Auto merge of #46706 - sunjay:gat-lifetimes, r=nikomatsakis
Lifetime Resolution for Generic Associated Types Tracking Issue: #44265 r? @nikomatsakis This PR implements lifetime resolution for generic associated types. 🎉 ## Remaining Work Before Merge I'm going to go do these things in the next day or so. Please let me know if you spot anything in my changes until then. - [x] If I'm not mistaken, at least some tests should pass now. I need to go through the tests and re-enable the ones that should work by removing the appropriate `~ ERROR` comments
2 parents 04b2344 + f701b4c commit b4f3232

9 files changed

+155
-53
lines changed

src/librustc/middle/resolve_lifetime.rs

+67-20
Original file line numberDiff line numberDiff line change
@@ -646,30 +646,77 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
646646
}
647647

648648
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
649-
let tcx = self.tcx;
650-
if let hir::TraitItemKind::Method(ref sig, _) = trait_item.node {
651-
self.visit_early_late(
652-
Some(tcx.hir.get_parent(trait_item.id)),
653-
&sig.decl,
654-
&trait_item.generics,
655-
|this| intravisit::walk_trait_item(this, trait_item),
656-
)
657-
} else {
658-
intravisit::walk_trait_item(self, trait_item);
649+
use self::hir::TraitItemKind::*;
650+
match trait_item.node {
651+
Method(ref sig, _) => {
652+
let tcx = self.tcx;
653+
self.visit_early_late(
654+
Some(tcx.hir.get_parent(trait_item.id)),
655+
&sig.decl,
656+
&trait_item.generics,
657+
|this| intravisit::walk_trait_item(this, trait_item),
658+
);
659+
},
660+
Type(ref bounds, ref ty) => {
661+
let generics = &trait_item.generics;
662+
let mut index = self.next_early_index();
663+
debug!("visit_ty: index = {}", index);
664+
let lifetimes = generics.lifetimes.iter()
665+
.map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def))
666+
.collect();
667+
668+
let next_early_index = index + generics.ty_params.len() as u32;
669+
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
670+
self.with(scope, |_old_scope, this| {
671+
this.visit_generics(generics);
672+
for bound in bounds {
673+
this.visit_ty_param_bound(bound);
674+
}
675+
if let Some(ty) = ty {
676+
this.visit_ty(ty);
677+
}
678+
});
679+
},
680+
Const(_, _) => {
681+
// Only methods and types support generics.
682+
assert!(!trait_item.generics.is_parameterized());
683+
intravisit::walk_trait_item(self, trait_item);
684+
},
659685
}
660686
}
661687

662688
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
663-
let tcx = self.tcx;
664-
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
665-
self.visit_early_late(
666-
Some(tcx.hir.get_parent(impl_item.id)),
667-
&sig.decl,
668-
&impl_item.generics,
669-
|this| intravisit::walk_impl_item(this, impl_item),
670-
)
671-
} else {
672-
intravisit::walk_impl_item(self, impl_item);
689+
use self::hir::ImplItemKind::*;
690+
match impl_item.node {
691+
Method(ref sig, _) => {
692+
let tcx = self.tcx;
693+
self.visit_early_late(
694+
Some(tcx.hir.get_parent(impl_item.id)),
695+
&sig.decl,
696+
&impl_item.generics,
697+
|this| intravisit::walk_impl_item(this, impl_item),
698+
)
699+
},
700+
Type(ref ty) => {
701+
let generics = &impl_item.generics;
702+
let mut index = self.next_early_index();
703+
debug!("visit_ty: index = {}", index);
704+
let lifetimes = generics.lifetimes.iter()
705+
.map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def))
706+
.collect();
707+
708+
let next_early_index = index + generics.ty_params.len() as u32;
709+
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
710+
self.with(scope, |_old_scope, this| {
711+
this.visit_generics(generics);
712+
this.visit_ty(ty);
713+
});
714+
},
715+
Const(_, _) => {
716+
// Only methods and types support generics.
717+
assert!(!impl_item.generics.is_parameterized());
718+
intravisit::walk_impl_item(self, impl_item);
719+
},
673720
}
674721
}
675722

src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
#![feature(generic_associated_types)]
1212

13-
//FIXME(#44265): "undeclared lifetime" errors will be addressed in a follow-up PR
13+
//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
14+
//follow-up PR
1415

1516
trait Foo {
1617
type Bar<'a, 'b>;
@@ -22,8 +23,7 @@ trait Baz {
2223

2324
impl<T> Baz for T where T: Foo {
2425
type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
25-
//~^ ERROR undeclared lifetime
26-
//~| ERROR lifetime parameters are not allowed on this type [E0110]
26+
//~^ ERROR lifetime parameters are not allowed on this type [E0110]
2727
}
2828

2929
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
error[E0261]: use of undeclared lifetime name `'a`
2-
--> $DIR/construct_with_other_type.rs:24:37
3-
|
4-
24 | type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
5-
| ^^ undeclared lifetime
6-
71
error[E0110]: lifetime parameters are not allowed on this type
8-
--> $DIR/construct_with_other_type.rs:24:37
2+
--> $DIR/construct_with_other_type.rs:25:37
93
|
10-
24 | type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
4+
25 | type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
115
| ^^ lifetime parameter not allowed on this type
126

13-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
148

src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs

-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
// Checking the interaction with this other feature
1414
#![feature(associated_type_defaults)]
1515

16-
//FIXME(#44265): "undeclared lifetime" errors will be addressed in a follow-up PR
17-
1816
use std::fmt::{Display, Debug};
1917

2018
trait Foo {
@@ -32,7 +30,6 @@ impl Foo for Bar {
3230
type Assoc2<T> = Vec<T>;
3331
type Assoc3<T> where T: Iterator = Vec<T>;
3432
type WithDefault<'a, T> = &'a Iterator<T>;
35-
//~^ ERROR undeclared lifetime
3633
type NoGenerics = ::std::cell::Cell<i32>;
3734
}
3835

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,2 @@
1-
error[E0261]: use of undeclared lifetime name `'a`
2-
--> $DIR/generic-associated-types-where.rs:34:32
3-
|
4-
34 | type WithDefault<'a, T> = &'a Iterator<T>;
5-
| ^^ undeclared lifetime
6-
71
error: cannot continue compilation due to previous error
82

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(generic_associated_types)]
12+
13+
use std::ops::Deref;
14+
15+
//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
16+
//follow-up PR
17+
18+
trait Iterable {
19+
type Item<'a>;
20+
type Iter<'a>: Iterator<Item = Self::Item<'a>>
21+
//~^ ERROR lifetime parameters are not allowed on this type [E0110]
22+
+ Deref<Target = Self::Item<'b>>;
23+
//~^ ERROR undeclared lifetime
24+
//~| ERROR lifetime parameters are not allowed on this type [E0110]
25+
26+
fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
27+
//~^ ERROR undeclared lifetime
28+
//~| ERROR lifetime parameters are not allowed on this type [E0110]
29+
}
30+
31+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0261]: use of undeclared lifetime name `'b`
2+
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37
3+
|
4+
22 | + Deref<Target = Self::Item<'b>>;
5+
| ^^ undeclared lifetime
6+
7+
error[E0261]: use of undeclared lifetime name `'undeclared`
8+
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41
9+
|
10+
26 | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
11+
| ^^^^^^^^^^^ undeclared lifetime
12+
13+
error[E0110]: lifetime parameters are not allowed on this type
14+
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:20:47
15+
|
16+
20 | type Iter<'a>: Iterator<Item = Self::Item<'a>>
17+
| ^^ lifetime parameter not allowed on this type
18+
19+
error[E0110]: lifetime parameters are not allowed on this type
20+
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37
21+
|
22+
22 | + Deref<Target = Self::Item<'b>>;
23+
| ^^ lifetime parameter not allowed on this type
24+
25+
error[E0110]: lifetime parameters are not allowed on this type
26+
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41
27+
|
28+
26 | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
29+
| ^^^^^^^^^^^ lifetime parameter not allowed on this type
30+
31+
error: aborting due to 5 previous errors
32+

src/test/ui/rfc1598-generic-associated-types/iterable.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@
1010

1111
#![feature(generic_associated_types)]
1212

13-
//FIXME(#44265): "undeclared lifetime" errors will be addressed in a follow-up PR
13+
use std::ops::Deref;
14+
15+
//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
16+
//follow-up PR
1417

1518
trait Iterable {
1619
type Item<'a>;
1720
type Iter<'a>: Iterator<Item = Self::Item<'a>>;
18-
//~^ ERROR undeclared lifetime
19-
//~| ERROR lifetime parameters are not allowed on this type [E0110]
21+
//~^ ERROR lifetime parameters are not allowed on this type [E0110]
22+
23+
// This weird type tests that we can use universal function call syntax to access the Item on
24+
// Self::Iter which we have declared to be an Iterator
25+
type Iter2<'a>: Deref<Target = <Self::Iter<'a> as Iterator>::Item>;
26+
//~^ ERROR lifetime parameters are not allowed on this type [E0110]
2027

2128
fn iter<'a>(&'a self) -> Self::Iter<'a>;
2229
//~^ ERROR lifetime parameters are not allowed on this type [E0110]

src/test/ui/rfc1598-generic-associated-types/iterable.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
error[E0261]: use of undeclared lifetime name `'a`
2-
--> $DIR/iterable.rs:17:47
1+
error[E0110]: lifetime parameters are not allowed on this type
2+
--> $DIR/iterable.rs:20:47
33
|
4-
17 | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
5-
| ^^ undeclared lifetime
4+
20 | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
5+
| ^^ lifetime parameter not allowed on this type
66

77
error[E0110]: lifetime parameters are not allowed on this type
8-
--> $DIR/iterable.rs:17:47
8+
--> $DIR/iterable.rs:25:48
99
|
10-
17 | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
11-
| ^^ lifetime parameter not allowed on this type
10+
25 | type Iter2<'a>: Deref<Target = <Self::Iter<'a> as Iterator>::Item>;
11+
| ^^ lifetime parameter not allowed on this type
1212

1313
error[E0110]: lifetime parameters are not allowed on this type
14-
--> $DIR/iterable.rs:21:41
14+
--> $DIR/iterable.rs:28:41
1515
|
16-
21 | fn iter<'a>(&'a self) -> Self::Iter<'a>;
16+
28 | fn iter<'a>(&'a self) -> Self::Iter<'a>;
1717
| ^^ lifetime parameter not allowed on this type
1818

1919
error: aborting due to 3 previous errors

0 commit comments

Comments
 (0)