Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize anonymous_lifetime_in_impl_trait #107378

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
c410-f3r marked this conversation as resolved.
Show resolved Hide resolved
}

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
Loading