Skip to content

Commit

Permalink
Stabilize anonymous_lifetime_in_impl_trait
Browse files Browse the repository at this point in the history
  • Loading branch information
c410-f3r committed Apr 21, 2024
1 parent f22a0c2 commit 6a202f5
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 116 deletions.
36 changes: 35 additions & 1 deletion compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1168,9 +1168,16 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
&& let hir::LifetimeName::Param(param_id) = lifetime_ref.res
&& let Some(generics) =
self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
&& let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
&& let Some((param, pred)) = generics
.params
.iter()
.position(|param| param.def_id == param_id)
.and_then(|idx| {
Some((generics.params.get(idx)?, generics.predicates.get(idx)?))
})
&& param.is_elided_lifetime()
&& !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
&& is_gat(pred)
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
{
let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err(
Expand Down Expand Up @@ -2106,3 +2113,30 @@ pub fn deny_non_region_late_bound(
*arg = ResolvedArg::Error(guar);
}
}

fn is_gat(predicate: &hir::WherePredicate<'_>) -> bool {
let hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bounds, .. }) = predicate
else {
return false;
};
for bound in *bounds {
let hir::GenericBound::Trait(poly_trait_ref, _) = bound else {
continue;
};

for segment in poly_trait_ref.trait_ref.path.segments {
let Some(generic_args) = segment.args else {
continue;
};
if !generic_args.args.is_empty() {
continue;
}
for binding in generic_args.bindings {
if !binding.gen_args.args.is_empty() {
return true;
}
}
}
}
false
}
60 changes: 60 additions & 0 deletions tests/ui/impl-trait/impl-trait-lifetimes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
trait Foo<T> {
fn foo(&self, _: T) { }
}

trait FooBar<'a> {
type Item;
}

mod foo {
fn fun(t: impl crate::Foo<&u32>, n: u32) {
t.foo(&n);
//~^ ERROR `n` does not live long enough
}
}

mod fun {
fn fun(t: impl Fn(&u32), n: u32) {
t(&n);
}
}

mod iterator_fun {
fn fun(t: impl Iterator<Item = impl Fn(&u32)>, n: u32) {
for elem in t {
elem(&n);
}
}
}

mod iterator_foo {
fn fun(t: impl Iterator<Item = impl crate::Foo<&u32>>, n: u32) {
for elem in t {
elem.foo(&n);
//~^ ERROR `n` does not live long enough
}
}
}

mod placeholder {
trait Placeholder<'a> {
fn foo(&self, _: &'a u32) {}
}

fn fun(t: impl Placeholder<'_>, n: u32) {
t.foo(&n);
//~^ ERROR `n` does not live long enough
}
}

mod stabilized {
trait InTrait {
fn in_trait(&self) -> impl Iterator<Item = &u32>;
}

fn foo1(_: impl Iterator<Item = &u32>) {}
fn foo2<'b>(_: impl crate::FooBar<'b, Item = &u32>) {}
}

fn main() {
}
43 changes: 43 additions & 0 deletions tests/ui/impl-trait/impl-trait-lifetimes.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
error[E0597]: `n` does not live long enough
--> $DIR/impl-trait-lifetimes.rs:11:15
|
LL | fn fun(t: impl crate::Foo<&u32>, n: u32) {
| - has type `t` - binding `n` declared here
LL | t.foo(&n);
| ------^^-
| | |
| | borrowed value does not live long enough
| argument requires that `n` is borrowed for `'1`
LL |
LL | }
| - `n` dropped here while still borrowed

error[E0597]: `n` does not live long enough
--> $DIR/impl-trait-lifetimes.rs:33:22
|
LL | fn fun(t: impl Iterator<Item = impl crate::Foo<&u32>>, n: u32) {
| - binding `n` declared here
LL | for elem in t {
LL | elem.foo(&n);
| ^^ borrowed value does not live long enough
...
LL | }
| - `n` dropped here while still borrowed

error[E0597]: `n` does not live long enough
--> $DIR/impl-trait-lifetimes.rs:45:15
|
LL | fn fun(t: impl Placeholder<'_>, n: u32) {
| - has type `t` - binding `n` declared here
LL | t.foo(&n);
| ------^^-
| | |
| | borrowed value does not live long enough
| argument requires that `n` is borrowed for `'1`
LL |
LL | }
| - `n` dropped here while still borrowed

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0597`.
33 changes: 33 additions & 0 deletions tests/ui/impl-trait/partial-anonymous-lifetime-in-impl-trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Incremental stabilization of `non-generic associated types` for non-generic associated types.

mod stabilized {
trait FooBar<'a> {
type Item;
}

fn foo0(x: impl Iterator<Item = &u32>) {
}

fn foo1<'b>(_: impl FooBar<'b, Item = &u32>) {
}
}

mod not_stabilized {
trait FooBar<'a> {
type Item;
}

trait LendingIterator {
type Item<'a>
where
Self: 'a;
}

fn foo0(_: impl LendingIterator<Item<'_> = &u32>) {}
//~^ ERROR `'_` cannot be used here
//~| ERROR anonymous lifetimes in `impl Trait` are unstable

fn foo1(_: impl FooBar<'_, Item = &u32>) {}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error[E0637]: `'_` cannot be used here
--> $DIR/partial-anonymous-lifetime-in-impl-trait.rs:26:42
|
LL | fn foo0(_: impl LendingIterator<Item<'_> = &u32>) {}
| ^^ `'_` is a reserved lifetime name

error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/partial-anonymous-lifetime-in-impl-trait.rs:26:49
|
LL | fn foo0(_: impl LendingIterator<Item<'_> = &u32>) {}
| ^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
help: consider introducing a named lifetime parameter
|
LL | fn foo0<'a>(_: impl LendingIterator<Item<'_> = &'a u32>) {}
| ++++ ++

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0637, E0658.
For more information about an error, try `rustc --explain E0637`.
21 changes: 9 additions & 12 deletions tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//@ edition:2021
// gate-test-anonymous_lifetime_in_impl_trait

// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`.

mod elided {
fn f(_: impl Iterator<Item = &()>) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable

fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~^ ERROR lifetime may not live long
//~| ERROR missing lifetime specifier

// Anonymous lifetimes in async fn are already allowed.
Expand All @@ -17,16 +17,15 @@ mod elided {
// Anonymous lifetimes in async fn are already allowed.
// But that lifetime does not participate in resolution.
async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
//~^ ERROR missing lifetime specifier
//~| ERROR lifetime may not live long enough
//~^ ERROR lifetime may not live long
//~| ERROR missing lifetime specifier
}

mod underscore {
fn f(_: impl Iterator<Item = &'_ ()>) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable

fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~^ ERROR lifetime may not live long
//~| ERROR missing lifetime specifier

// Anonymous lifetimes in async fn are already allowed.
Expand All @@ -36,29 +35,27 @@ mod underscore {
// Anonymous lifetimes in async fn are already allowed.
// But that lifetime does not participate in resolution.
async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR missing lifetime specifier
//~| ERROR lifetime may not live long enough
//~^ ERROR lifetime may not live long
//~| ERROR missing lifetime specifier
}

mod alone_in_path {
trait Foo<'a> { fn next(&mut self) -> Option<&'a ()>; }

fn f(_: impl Foo) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable

fn g(mut x: impl Foo) -> Option<&()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~^ ERROR lifetime may not live long
//~| ERROR missing lifetime specifier
}

mod in_path {
trait Foo<'a, T> { fn next(&mut self) -> Option<&'a T>; }

fn f(_: impl Foo<()>) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable

fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~^ ERROR lifetime may not live long
//~| ERROR missing lifetime specifier
}

Expand Down
Loading

0 comments on commit 6a202f5

Please sign in to comment.