From 1b73e54f68b7ee1f08698415d169809d7911b169 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 12 May 2022 13:35:42 +0000 Subject: [PATCH 1/2] Forbid lifetime bounds in nested opaque types in binders --- compiler/rustc_ast_lowering/src/item.rs | 10 +- compiler/rustc_ast_lowering/src/lib.rs | 154 +++++++++++------- compiler/rustc_ast_lowering/src/path.rs | 19 ++- src/test/ui/associated-type-bounds/rpit.rs | 3 +- .../ui/associated-type-bounds/rpit.stderr | 10 ++ src/test/ui/impl-trait/issues/issue-54895.rs | 3 +- .../ui/impl-trait/issues/issue-54895.stderr | 10 ++ src/test/ui/impl-trait/issues/issue-67830.rs | 1 + .../ui/impl-trait/issues/issue-67830.stderr | 10 +- .../ui/impl-trait/issues/issue-88236-2.rs | 12 ++ .../ui/impl-trait/issues/issue-88236-2.stderr | 47 +++++- src/test/ui/impl-trait/issues/issue-88236.rs | 3 +- .../ui/impl-trait/issues/issue-88236.stderr | 10 ++ 13 files changed, 218 insertions(+), 74 deletions(-) create mode 100644 src/test/ui/associated-type-bounds/rpit.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-54895.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-88236.stderr diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cf97b270ed8f9..4af850b3ec14e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1353,6 +1353,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ¶m.kind, bounds, PredicateOrigin::GenericParam, + itctx.reborrow(), ) })); predicates.extend( @@ -1388,6 +1389,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: &GenericParamKind, bounds: &'hir [hir::GenericBound<'hir>], origin: PredicateOrigin, + itctx: ImplTraitContext<'_, 'hir>, ) -> Option> { // Do not create a clause if we do not have anything inside it. if bounds.is_empty() { @@ -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, @@ -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), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c143266f6c1de..a7b82d92498f5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -267,6 +267,9 @@ enum ImplTraitContext<'b, 'a> { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, + /// Whether this is nested in another return position opaque type + /// `None` if we aren't in any return position opaque type yet. + nested: Option, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, @@ -303,7 +306,9 @@ impl<'a> ImplTraitContext<'_, 'a> { use self::ImplTraitContext::*; match self { Universal(params, bounds, parent) => Universal(params, bounds, *parent), - ReturnPositionOpaqueTy { origin } => ReturnPositionOpaqueTy { origin: *origin }, + ReturnPositionOpaqueTy { origin, nested } => { + ReturnPositionOpaqueTy { origin: *origin, nested: *nested } + } TypeAliasesOpaqueTy => TypeAliasesOpaqueTy, Disallowed(pos) => Disallowed(*pos), } @@ -1072,7 +1077,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: ImplTraitContext<'_, 'hir>, ) -> hir::GenericArg<'hir> { match arg { - ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), + ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<, itctx)), ast::GenericArg::Type(ty) => { match ty.kind { TyKind::Infer if self.sess.features_untracked().generic_arg_infer => { @@ -1179,7 +1184,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { id: start, } }); - let lifetime = self.lower_lifetime(®ion); + let lifetime = self.lower_lifetime(®ion, itctx.reborrow()); hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| { @@ -1239,7 +1244,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) => None, GenericBound::Outlives(ref lifetime) => { if lifetime_bound.is_none() { - lifetime_bound = Some(this.lower_lifetime(lifetime)); + lifetime_bound = + Some(this.lower_lifetime(lifetime, itctx.reborrow())); } None } @@ -1254,17 +1260,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin } => self - .lower_opaque_impl_trait(span, origin, def_node_id, |this| { - this.lower_param_bounds(bounds, itctx) - }), + ImplTraitContext::ReturnPositionOpaqueTy { origin, nested } => self + .lower_opaque_impl_trait( + span, + origin, + def_node_id, + |this, itctx| this.lower_param_bounds(bounds, itctx), + ImplTraitContext::ReturnPositionOpaqueTy { + origin, + nested: match nested { + Some(_) => Some(true), + None => Some(false), + }, + }, + ), ImplTraitContext::TypeAliasesOpaqueTy => { let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; self.lower_opaque_impl_trait( span, hir::OpaqueTyOrigin::TyAlias, def_node_id, - |this| this.lower_param_bounds(bounds, nested_itctx), + |this, itctx| this.lower_param_bounds(bounds, itctx), + nested_itctx, ) } ImplTraitContext::Universal( @@ -1299,6 +1316,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &GenericParamKind::Type { default: None }, hir_bounds, hir::PredicateOrigin::ImplTrait, + ImplTraitContext::Universal( + in_band_ty_params, + in_band_ty_bounds, + parent_def_id, + ), ) { in_band_ty_bounds.push(preds) } @@ -1344,7 +1366,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, - lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, + lower_bounds: impl FnOnce(&mut Self, ImplTraitContext<'_, 'hir>) -> hir::GenericBounds<'hir>, + mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1358,13 +1381,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut collected_lifetimes = FxHashMap::default(); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias { - lower_bounds(lctx) + lower_bounds(lctx, itctx.reborrow()) } else { - lctx.while_capturing_lifetimes( - opaque_ty_def_id, - &mut collected_lifetimes, - lower_bounds, - ) + lctx.while_capturing_lifetimes(opaque_ty_def_id, &mut collected_lifetimes, |lctx| { + lower_bounds(lctx, itctx.reborrow()) + }) }; debug!(?collected_lifetimes); @@ -1412,7 +1433,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { |(_, (span, _, p_name, res))| { let id = self.resolver.next_node_id(); let ident = Ident::new(p_name.ident().name, span); - let l = self.new_named_lifetime_with_res(id, span, ident, res); + let l = self.new_named_lifetime_with_res(id, span, ident, res, itctx.reborrow()); hir::GenericArg::Lifetime(l) }, )); @@ -1523,35 +1544,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } })); + let context = match in_band_ty_params { + Some((node_id, _, _)) if kind.impl_trait_return_allowed() => { + let fn_def_id = self.resolver.local_def_id(node_id); + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + nested: None, + } + } + _ => ImplTraitContext::Disallowed(match kind { + FnDeclKind::Fn | FnDeclKind::Inherent => { + unreachable!("fn should allow in-band lifetimes") + } + FnDeclKind::ExternFn => ImplTraitPosition::ExternFnReturn, + FnDeclKind::Closure => ImplTraitPosition::ClosureReturn, + FnDeclKind::Pointer => ImplTraitPosition::PointerReturn, + FnDeclKind::Trait => ImplTraitPosition::TraitReturn, + FnDeclKind::Impl => ImplTraitPosition::ImplReturn, + }), + }; + let output = if let Some(ret_id) = make_ret_async { self.lower_async_fn_ret_ty( &decl.output, in_band_ty_params.expect("`make_ret_async` but no `fn_def_id`").0, ret_id, + context, ) } else { match decl.output { - FnRetTy::Ty(ref ty) => { - let context = match in_band_ty_params { - Some((node_id, _, _)) if kind.impl_trait_return_allowed() => { - let fn_def_id = self.resolver.local_def_id(node_id); - ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - } - } - _ => ImplTraitContext::Disallowed(match kind { - FnDeclKind::Fn | FnDeclKind::Inherent => { - unreachable!("fn should allow in-band lifetimes") - } - FnDeclKind::ExternFn => ImplTraitPosition::ExternFnReturn, - FnDeclKind::Closure => ImplTraitPosition::ClosureReturn, - FnDeclKind::Pointer => ImplTraitPosition::PointerReturn, - FnDeclKind::Trait => ImplTraitPosition::TraitReturn, - FnDeclKind::Impl => ImplTraitPosition::ImplReturn, - }), - }; - hir::FnRetTy::Return(self.lower_ty(ty, context)) - } + FnRetTy::Ty(ref ty) => hir::FnRetTy::Return(self.lower_ty(ty, context)), FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)), } }; @@ -1603,6 +1625,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output: &FnRetTy, fn_node_id: NodeId, opaque_ty_node_id: NodeId, + mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::FnRetTy<'hir> { let span = output.span(); @@ -1765,7 +1788,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc_from_iter(captures.into_iter().map(|(_, (span, _, p_name, res))| { let id = self.resolver.next_node_id(); let ident = Ident::new(p_name.ident().name, span); - let l = self.new_named_lifetime_with_res(id, span, ident, res); + let l = self.new_named_lifetime_with_res(id, span, ident, res, itctx.reborrow()); hir::GenericArg::Lifetime(l) })); @@ -1794,6 +1817,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + nested: None, }; self.lower_ty(ty, context) } @@ -1828,19 +1852,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_trait_bound_modifier(*modifier), ), GenericBound::Outlives(lifetime) => { - hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) + hir::GenericBound::Outlives(self.lower_lifetime(lifetime, itctx)) } } } - fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { + fn lower_lifetime(&mut self, l: &Lifetime, itctx: ImplTraitContext<'_, 'hir>) -> hir::Lifetime { let span = self.lower_span(l.ident.span); let ident = self.lower_ident(l.ident); let res = self .resolver .get_lifetime_res(l.id) .unwrap_or_else(|| panic!("Missing resolution for lifetime {:?} at {:?}", l, span)); - self.new_named_lifetime_with_res(l.id, span, ident, res) + self.new_named_lifetime_with_res(l.id, span, ident, res, itctx) } #[tracing::instrument(level = "debug", skip(self))] @@ -1850,6 +1874,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, ident: Ident, res: LifetimeRes, + itctx: ImplTraitContext<'_, 'hir>, ) -> hir::Lifetime { debug!(?self.captured_lifetimes); let name = match res { @@ -1858,21 +1883,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let p_name = ParamName::Plain(ident); if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) = &mut self.captured_lifetimes - && !binders_to_ignore.contains(&binder) { - match captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let p_id = self.resolver.next_node_id(); - self.resolver.create_def( - *parent_def_id, - p_id, - DefPathData::LifetimeNs(p_name.ident().name), - ExpnId::root(), - span.with_parent(None), - ); + if binders_to_ignore.contains(&binder) { + match itctx { + ImplTraitContext::ReturnPositionOpaqueTy { + nested: Some(true), .. + } + | ImplTraitContext::TypeAliasesOpaqueTy => { + let mut err = self.sess.struct_span_err( + span, + "higher kinded lifetime bounds on nested opaque types are not supported yet", + ); + if let Some(&(span, _, _, _)) = captures.get(¶m) { + err.span_note(span, "lifetime declared here"); + } + err.help("See https://github.com/rust-lang/rust/issues/96194 for further details"); + err.emit(); + } + _ => {} + } + } else { + match captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let p_id = self.resolver.next_node_id(); + self.resolver.create_def( + *parent_def_id, + p_id, + DefPathData::LifetimeNs(p_name.ident().name), + ExpnId::root(), + span.with_parent(None), + ); - v.insert((span, p_id, p_name, res)); + v.insert((span, p_id, p_name, res)); + } } } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 3c9399c1fdf80..e1c0f08e06db5 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -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 => { @@ -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, @@ -248,6 +248,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment.id, segment.ident.span, &mut generic_args, + itctx, ); } @@ -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), @@ -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) }), ); diff --git a/src/test/ui/associated-type-bounds/rpit.rs b/src/test/ui/associated-type-bounds/rpit.rs index 47cadf3310bd8..03af2a22613e8 100644 --- a/src/test/ui/associated-type-bounds/rpit.rs +++ b/src/test/ui/associated-type-bounds/rpit.rs @@ -1,5 +1,3 @@ -// run-pass - #![feature(associated_type_bounds)] use std::ops::Add; @@ -42,6 +40,7 @@ pub fn use_et3() { } fn def_et4() -> impl Tr1 Tr2<'a>> { + //~^ ERROR lifetime bounds on nested opaque types are not supported yet #[derive(Copy, Clone)] struct A; impl Tr1 for A { diff --git a/src/test/ui/associated-type-bounds/rpit.stderr b/src/test/ui/associated-type-bounds/rpit.stderr new file mode 100644 index 0000000000000..716f1106a9080 --- /dev/null +++ b/src/test/ui/associated-type-bounds/rpit.stderr @@ -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 Tr2<'a>> { + | ^^ + | + = help: See https://github.com/rust-lang/rust/issues/96194 for further details + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/issues/issue-54895.rs b/src/test/ui/impl-trait/issues/issue-54895.rs index a70166e03a7b1..0eba8c7f5740c 100644 --- a/src/test/ui/impl-trait/issues/issue-54895.rs +++ b/src/test/ui/impl-trait/issues/issue-54895.rs @@ -1,5 +1,3 @@ -// check-pass - trait Trait<'a> { type Out; fn call(&'a self) -> Self::Out; @@ -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(()) } diff --git a/src/test/ui/impl-trait/issues/issue-54895.stderr b/src/test/ui/impl-trait/issues/issue-54895.stderr new file mode 100644 index 0000000000000..ac6083f9e0f40 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-54895.stderr @@ -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 + diff --git a/src/test/ui/impl-trait/issues/issue-67830.rs b/src/test/ui/impl-trait/issues/issue-67830.rs index a308d975b4395..570be81d844dd 100644 --- a/src/test/ui/impl-trait/issues/issue-67830.rs +++ b/src/test/ui/impl-trait/issues/issue-67830.rs @@ -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()) } diff --git a/src/test/ui/impl-trait/issues/issue-67830.stderr b/src/test/ui/impl-trait/issues/issue-67830.stderr index 4c0490c721bc4..847d605b4d514 100644 --- a/src/test/ui/impl-trait/issues/issue-67830.stderr +++ b/src/test/ui/impl-trait/issues/issue-67830.stderr @@ -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 | @@ -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 diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.rs b/src/test/ui/impl-trait/issues/issue-88236-2.rs index af26a1f54c46d..7a149f9709da5 100644 --- a/src/test/ui/impl-trait/issues/issue-88236-2.rs +++ b/src/test/ui/impl-trait/issues/issue-88236-2.rs @@ -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() {} diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.stderr index 9574b880f7d11..f0ac6429333c5 100644 --- a/src/test/ui/impl-trait/issues/issue-88236-2.stderr +++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr @@ -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 @@ -8,7 +40,7 @@ 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 @@ -16,5 +48,14 @@ LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send = 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 diff --git a/src/test/ui/impl-trait/issues/issue-88236.rs b/src/test/ui/impl-trait/issues/issue-88236.rs index 2ea35270a7e3b..27d58714184ff 100644 --- a/src/test/ui/impl-trait/issues/issue-88236.rs +++ b/src/test/ui/impl-trait/issues/issue-88236.rs @@ -1,5 +1,3 @@ -// check-pass - // this used to cause stack overflows trait Hrtb<'a> { @@ -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() {} diff --git a/src/test/ui/impl-trait/issues/issue-88236.stderr b/src/test/ui/impl-trait/issues/issue-88236.stderr new file mode 100644 index 0000000000000..87ca43e0daaeb --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-88236.stderr @@ -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 + From 193a16b313b4b227424472f0073065ed6927827a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 13 May 2022 07:36:37 +0000 Subject: [PATCH 2/2] Also check anonymous and fresh lifetimes, even if they should never appear in practice --- compiler/rustc_ast_lowering/src/lib.rs | 115 +++++++++++++++---------- 1 file changed, 70 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a7b82d92498f5..b91a4d11e09fc 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1876,6 +1876,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { res: LifetimeRes, itctx: ImplTraitContext<'_, 'hir>, ) -> hir::Lifetime { + fn check_impl_trait_lifetimes( + sess: &Session, + itctx: ImplTraitContext<'_, '_>, + span: Span, + note_span: Option, + ) { + match itctx { + ImplTraitContext::ReturnPositionOpaqueTy { nested: Some(true), .. } + | ImplTraitContext::TypeAliasesOpaqueTy => { + let mut err = sess.struct_span_err( + span, + "higher kinded lifetime bounds on nested opaque types are not supported yet", + ); + if let Some(span) = note_span { + err.span_note(span, "lifetime declared here"); + } + err.help( + "See https://github.com/rust-lang/rust/issues/96194 for further details", + ); + err.emit(); + } + _ => {} + } + } debug!(?self.captured_lifetimes); let name = match res { LifetimeRes::Param { param, binder } => { @@ -1885,23 +1909,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self.captured_lifetimes { if binders_to_ignore.contains(&binder) { - match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { - nested: Some(true), .. - } - | ImplTraitContext::TypeAliasesOpaqueTy => { - let mut err = self.sess.struct_span_err( - span, - "higher kinded lifetime bounds on nested opaque types are not supported yet", - ); - if let Some(&(span, _, _, _)) = captures.get(¶m) { - err.span_note(span, "lifetime declared here"); - } - err.help("See https://github.com/rust-lang/rust/issues/96194 for further details"); - err.emit(); - } - _ => {} - } + check_impl_trait_lifetimes( + self.sess, + itctx, + span, + captures.get(¶m).map(|cap| cap.0), + ); } else { match captures.entry(param) { Entry::Occupied(_) => {} @@ -1926,23 +1939,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) = &mut self.captured_lifetimes - && !binders_to_ignore.contains(&binder) { - match captures.entry(param) { - Entry::Occupied(o) => param = self.resolver.local_def_id(o.get().1), - Entry::Vacant(v) => { - let p_id = self.resolver.next_node_id(); - let p_def_id = self.resolver.create_def( - *parent_def_id, - p_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ExpnId::root(), - span.with_parent(None), - ); - - let p_name = ParamName::Fresh(param); - v.insert((span, p_id, p_name, res)); - param = p_def_id; + if binders_to_ignore.contains(&binder) { + check_impl_trait_lifetimes( + self.sess, + itctx, + span, + captures.get(¶m).map(|cap| cap.0), + ); + } else { + match captures.entry(param) { + Entry::Occupied(o) => param = self.resolver.local_def_id(o.get().1), + Entry::Vacant(v) => { + let p_id = self.resolver.next_node_id(); + let p_def_id = self.resolver.create_def( + *parent_def_id, + p_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ExpnId::root(), + span.with_parent(None), + ); + + let p_name = ParamName::Fresh(param); + v.insert((span, p_id, p_name, res)); + param = p_def_id; + } } } } @@ -1957,19 +1978,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) = &mut self.captured_lifetimes - && !binders_to_ignore.contains(&binder) { - let p_id = self.resolver.next_node_id(); - let p_def_id = self.resolver.create_def( - *parent_def_id, - p_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ExpnId::root(), - span.with_parent(None), - ); - let p_name = ParamName::Fresh(p_def_id); - captures.insert(p_def_id, (span, p_id, p_name, res)); - hir::LifetimeName::Param(p_name) + if binders_to_ignore.contains(&binder) { + check_impl_trait_lifetimes(self.sess, itctx, span, None); + l_name + } else { + let p_id = self.resolver.next_node_id(); + let p_def_id = self.resolver.create_def( + *parent_def_id, + p_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ExpnId::root(), + span.with_parent(None), + ); + let p_name = ParamName::Fresh(p_def_id); + captures.insert(p_def_id, (span, p_id, p_name, res)); + hir::LifetimeName::Param(p_name) + } } else { l_name }