Skip to content

Forbid lifetime bounds in nested opaque types in binders #96970

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

Closed
Closed
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
10 changes: 8 additions & 2 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&param.kind,
bounds,
PredicateOrigin::GenericParam,
itctx.reborrow(),
)
}));
predicates.extend(
Expand Down Expand Up @@ -1388,6 +1389,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
kind: &GenericParamKind,
bounds: &'hir [hir::GenericBound<'hir>],
origin: PredicateOrigin,
itctx: ImplTraitContext<'_, 'hir>,
) -> Option<hir::WherePredicate<'hir>> {
// Do not create a clause if we do not have anything inside it.
if bounds.is_empty() {
Expand Down Expand Up @@ -1437,7 +1439,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
panic!("Missing resolution for lifetime {:?} at {:?}", id, ident.span)
});
let lt_id = self.resolver.next_node_id();
let lifetime = self.new_named_lifetime_with_res(lt_id, ident_span, ident, res);
let lifetime =
self.new_named_lifetime_with_res(lt_id, ident_span, ident, res, itctx);
Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
lifetime,
span,
Expand Down Expand Up @@ -1474,7 +1477,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
span,
}) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
span: self.lower_span(span),
lifetime: self.lower_lifetime(lifetime),
lifetime: self.lower_lifetime(
lifetime,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
),
bounds: self.lower_param_bounds(
bounds,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
Expand Down
237 changes: 153 additions & 84 deletions compiler/rustc_ast_lowering/src/lib.rs

Large diffs are not rendered by default.

19 changes: 12 additions & 7 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
segment: &PathSegment,
param_mode: ParamMode,
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: ImplTraitContext<'_, 'hir>,
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::PathSegment<'hir> {
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
let msg = "parenthesized type parameters may only be used with a `Fn` trait";
match **generic_args {
GenericArgs::AngleBracketed(ref data) => {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx.reborrow())
}
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
ParenthesizedGenericArgs::Ok => {
Expand Down Expand Up @@ -220,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_angle_bracketed_parameter_data(
&data.as_angle_bracketed_args(),
param_mode,
itctx,
itctx.reborrow(),
)
.0,
false,
Expand Down Expand Up @@ -248,6 +248,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
segment.id,
segment.ident.span,
&mut generic_args,
itctx,
);
}

Expand Down Expand Up @@ -277,6 +278,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
segment_id: NodeId,
segment_ident_span: Span,
generic_args: &mut GenericArgsCtor<'hir>,
mut itctx: ImplTraitContext<'_, 'hir>,
) {
let (start, end) = match self.resolver.get_lifetime_res(segment_id) {
Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end),
Expand Down Expand Up @@ -305,10 +307,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
0,
(start.as_u32()..end.as_u32()).map(|i| {
let id = NodeId::from_u32(i);
let l = self.lower_lifetime(&Lifetime {
id,
ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span),
});
let l = self.lower_lifetime(
&Lifetime {
id,
ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span),
},
itctx.reborrow(),
);
GenericArg::Lifetime(l)
}),
);
Expand Down
3 changes: 1 addition & 2 deletions src/test/ui/associated-type-bounds/rpit.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// run-pass

#![feature(associated_type_bounds)]

use std::ops::Add;
Expand Down Expand Up @@ -42,6 +40,7 @@ pub fn use_et3() {
}

fn def_et4() -> impl Tr1<As1: for<'a> Tr2<'a>> {
//~^ ERROR lifetime bounds on nested opaque types are not supported yet
#[derive(Copy, Clone)]
struct A;
impl Tr1 for A {
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/associated-type-bounds/rpit.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/rpit.rs:42:43
|
LL | fn def_et4() -> impl Tr1<As1: for<'a> Tr2<'a>> {
| ^^
|
= help: See https://github.com/rust-lang/rust/issues/96194 for further details

error: aborting due to previous error

3 changes: 1 addition & 2 deletions src/test/ui/impl-trait/issues/issue-54895.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// check-pass

trait Trait<'a> {
type Out;
fn call(&'a self) -> Self::Out;
Expand All @@ -15,6 +13,7 @@ impl<'a> Trait<'a> for X {
}

fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
//~^ ERROR lifetime bounds on nested opaque types are not supported yet
X(())
}

Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/impl-trait/issues/issue-54895.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-54895.rs:15:53
|
LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
| ^^
|
= help: See https://github.com/rust-lang/rust/issues/96194 for further details

error: aborting due to previous error

1 change: 1 addition & 0 deletions src/test/ui/impl-trait/issues/issue-67830.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ where
struct A;
fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
//~^ ERROR implementation of `FnOnce` is not general enough
//~| ERROR lifetime bounds on nested opaque types are not supported yet
Wrap(|a| Some(a).into_iter())
}

Expand Down
10 changes: 9 additions & 1 deletion src/test/ui/impl-trait/issues/issue-67830.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-67830.rs:21:62
|
LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
| ^^
|
= help: See https://github.com/rust-lang/rust/issues/96194 for further details

error: implementation of `FnOnce` is not general enough
--> $DIR/issue-67830.rs:21:14
|
Expand All @@ -7,5 +15,5 @@ LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
= note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`

error: aborting due to previous error
error: aborting due to 2 previous errors

12 changes: 12 additions & 0 deletions src/test/ui/impl-trait/issues/issue-88236-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,23 @@ impl<'a> Hrtb<'a> for &'a () {
}

fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
//~^ ERROR lifetime bounds on nested opaque types are not supported yet
fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
&() //~^ ERROR implementation of `Hrtb` is not general enough
//~| ERROR lifetime bounds on nested opaque types are not supported yet
}
fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
x //~^ ERROR implementation of `Hrtb` is not general enough
//~| ERROR lifetime bounds on nested opaque types are not supported yet
}

trait Zend<'a>: Send {}

impl<'a, T: Send> Zend<'a> for T {}

fn make_bad_impl_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a>> {
x //~^ ERROR implementation of `Hrtb` is not general enough
//~| ERROR lifetime bounds on nested opaque types are not supported yet
}

fn main() {}
47 changes: 44 additions & 3 deletions src/test/ui/impl-trait/issues/issue-88236-2.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236-2.rs:15:61
|
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^
|
= help: See https://github.com/rust-lang/rust/issues/96194 for further details

error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236-2.rs:17:80
|
LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^
|
= help: See https://github.com/rust-lang/rust/issues/96194 for further details

error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236-2.rs:21:78
|
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^
|
= help: See https://github.com/rust-lang/rust/issues/96194 for further details

error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236-2.rs:30:78
|
LL | fn make_bad_impl_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a>> {
| ^^
|
= help: See https://github.com/rust-lang/rust/issues/96194 for further details

error: implementation of `Hrtb` is not general enough
--> $DIR/issue-88236-2.rs:16:38
--> $DIR/issue-88236-2.rs:17:38
|
LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Hrtb` is not general enough
Expand All @@ -8,13 +40,22 @@ LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Sen
= note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`

error: implementation of `Hrtb` is not general enough
--> $DIR/issue-88236-2.rs:19:36
--> $DIR/issue-88236-2.rs:21:36
|
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Hrtb` is not general enough
|
= note: `Hrtb<'1>` would have to be implemented for the type `&()`, for any lifetime `'1`...
= note: ...but `Hrtb<'_>` is actually implemented for the type `&()`

error: aborting due to 2 previous errors
error: implementation of `Hrtb` is not general enough
--> $DIR/issue-88236-2.rs:30:38
|
LL | fn make_bad_impl_2<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Zend<'a>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Hrtb` is not general enough
|
= note: `Hrtb<'1>` would have to be implemented for the type `&()`, for any lifetime `'1`...
= note: ...but `Hrtb<'_>` is actually implemented for the type `&()`

error: aborting due to 7 previous errors

3 changes: 1 addition & 2 deletions src/test/ui/impl-trait/issues/issue-88236.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// check-pass

// this used to cause stack overflows

trait Hrtb<'a> {
Expand All @@ -15,5 +13,6 @@ impl<'a> Hrtb<'a> for &'a () {
}

fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
//~^ ERROR lifetime bounds on nested opaque types are not supported yet

fn main() {}
10 changes: 10 additions & 0 deletions src/test/ui/impl-trait/issues/issue-88236.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: higher kinded lifetime bounds on nested opaque types are not supported yet
--> $DIR/issue-88236.rs:15:61
|
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^
|
= help: See https://github.com/rust-lang/rust/issues/96194 for further details

error: aborting due to previous error