From a87ab480999e21de80b12ad6de6a777c70bebaab Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Dec 2021 00:07:21 +0100 Subject: [PATCH 01/11] Ban non-static in const generics in AST. --- compiler/rustc_resolve/src/late.rs | 23 ++++++++++--- .../rustc_resolve/src/late/diagnostics.rs | 33 +++++++++---------- compiler/rustc_resolve/src/late/lifetimes.rs | 11 ------- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9ea66c0b59d9f..f5e8eca8fcb2e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -199,6 +199,11 @@ enum LifetimeRibKind { /// This rib declares generic parameters. Generics { parent: NodeId, span: Span, kind: LifetimeBinderKind }, + /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const + /// generics. We are disallowing this until we can decide on how we want to handle non-'static + /// lifetimes in const generics. See issue #74052 for discussion. + ConstGeneric, + /// For **Modern** cases, create a new anonymous region parameter /// and reference that. /// @@ -1102,14 +1107,18 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); this.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); - this.visit_ty(ty); + this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { + this.visit_ty(ty) + }); this.ribs[TypeNS].pop().unwrap(); this.ribs[ValueNS].pop().unwrap(); if let Some(ref expr) = default { this.ribs[TypeNS].push(forward_ty_ban_rib); this.ribs[ValueNS].push(forward_const_ban_rib); - this.visit_anon_const(expr); + this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { + this.visit_anon_const(expr) + }); forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap(); forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap(); } @@ -1158,8 +1167,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { return; } - if let LifetimeRibKind::Item = rib.kind { - break; + match rib.kind { + LifetimeRibKind::Item => break, + LifetimeRibKind::ConstGeneric => { + self.emit_non_static_lt_in_const_generic_error(lifetime); + self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error); + return; + } + _ => {} } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a9edb713b0da7..b153c9f95267f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1886,6 +1886,21 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.emit(); } + + crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &ast::Lifetime) { + struct_span_err!( + self.r.session, + lifetime_ref.ident.span, + E0771, + "use of non-static lifetime `{}` in const generic", + lifetime_ref.ident + ) + .note( + "for more information, see issue #74052 \ + ", + ) + .emit(); + } } impl<'tcx> LifetimeContext<'_, 'tcx> { @@ -1982,24 +1997,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { } } - // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const - // generics. We are disallowing this until we can decide on how we want to handle non-'static - // lifetimes in const generics. See issue #74052 for discussion. - crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &hir::Lifetime) { - let mut err = struct_span_err!( - self.tcx.sess, - lifetime_ref.span, - E0771, - "use of non-static lifetime `{}` in const generic", - lifetime_ref - ); - err.note( - "for more information, see issue #74052 \ - ", - ); - err.emit(); - } - crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool { if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res { if [ diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index ce3069265d020..6bb0c3b5e6b59 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -164,8 +164,6 @@ crate struct LifetimeContext<'a, 'tcx> { map: &'a mut NamedRegionMap, scope: ScopeRef<'a>, - is_in_const_generic: bool, - /// Indicates that we only care about the definition of a trait. This should /// be false if the `Item` we are resolving lifetimes for is not a trait or /// we eventually need lifetimes resolve for trait items. @@ -452,7 +450,6 @@ fn do_resolve( tcx, map: &mut named_region_map, scope: ROOT_SCOPE, - is_in_const_generic: false, trait_definition_only, labels_in_fn: vec![], xcrate_object_lifetime_defaults: Default::default(), @@ -1266,10 +1263,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.insert_lifetime(lifetime_ref, Region::Static); return; } - if self.is_in_const_generic && lifetime_ref.name != LifetimeName::Error { - self.emit_non_static_lt_in_const_generic_error(lifetime_ref); - return; - } self.resolve_lifetime_ref(lifetime_ref); } @@ -1341,14 +1334,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } GenericParamKind::Const { ref ty, default } => { - let was_in_const_generic = this.is_in_const_generic; - this.is_in_const_generic = true; walk_list!(this, visit_param_bound, param.bounds); this.visit_ty(&ty); if let Some(default) = default { this.visit_body(this.tcx.hir().body(default.body)); } - this.is_in_const_generic = was_in_const_generic; } } } @@ -1798,7 +1788,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { tcx: *tcx, map, scope: &wrap_scope, - is_in_const_generic: self.is_in_const_generic, trait_definition_only: self.trait_definition_only, labels_in_fn, xcrate_object_lifetime_defaults, From b711723d415bdadb3b1a6cc2458f05480c06b49b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 8 Dec 2021 22:51:39 +0100 Subject: [PATCH 02/11] Bless tests. --- .../issues/issue-56445-1.min.stderr | 11 ++++++++++- .../ui/const-generics/issues/issue-56445-1.rs | 1 + src/test/ui/error-codes/E0771.stderr | 16 ++++++++-------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/test/ui/const-generics/issues/issue-56445-1.min.stderr b/src/test/ui/const-generics/issues/issue-56445-1.min.stderr index 179643a755293..43a5df117fdc7 100644 --- a/src/test/ui/const-generics/issues/issue-56445-1.min.stderr +++ b/src/test/ui/const-generics/issues/issue-56445-1.min.stderr @@ -6,6 +6,15 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | = note: for more information, see issue #74052 -error: aborting due to previous error +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/issue-56445-1.rs:9:25 + | +LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0771`. diff --git a/src/test/ui/const-generics/issues/issue-56445-1.rs b/src/test/ui/const-generics/issues/issue-56445-1.rs index aeef778991f06..13eb2ea9f69d5 100644 --- a/src/test/ui/const-generics/issues/issue-56445-1.rs +++ b/src/test/ui/const-generics/issues/issue-56445-1.rs @@ -8,5 +8,6 @@ use std::marker::PhantomData; struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); //~^ ERROR: use of non-static lifetime `'a` in const generic +//[min]~| ERROR: `&'static str` is forbidden as the type of a const generic parameter impl Bug<'_, ""> {} diff --git a/src/test/ui/error-codes/E0771.stderr b/src/test/ui/error-codes/E0771.stderr index 5a16d5845a60e..3ab727f5f69da 100644 --- a/src/test/ui/error-codes/E0771.stderr +++ b/src/test/ui/error-codes/E0771.stderr @@ -1,3 +1,11 @@ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/E0771.rs:4:41 + | +LL | fn function_with_str<'a, const STRING: &'a str>() {} + | ^^ + | + = note: for more information, see issue #74052 + warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/E0771.rs:1:12 | @@ -7,14 +15,6 @@ LL | #![feature(adt_const_params)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #95174 for more information -error[E0771]: use of non-static lifetime `'a` in const generic - --> $DIR/E0771.rs:4:41 - | -LL | fn function_with_str<'a, const STRING: &'a str>() {} - | ^^ - | - = note: for more information, see issue #74052 - error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0771`. From 865d0fef2f49de54c89132672946cefb8b8a8f10 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 31 Mar 2022 20:10:37 +0200 Subject: [PATCH 03/11] Ban non-static lifetimes from AnonConst on AST. The extra diagnostics come from the compiler no longer aborting before typeck. --- compiler/rustc_resolve/src/late.rs | 27 +++++++++--- .../rustc_resolve/src/late/diagnostics.rs | 44 +++++++------------ compiler/rustc_resolve/src/late/lifetimes.rs | 4 -- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f5e8eca8fcb2e..9622553319d95 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -204,6 +204,11 @@ enum LifetimeRibKind { /// lifetimes in const generics. See issue #74052 for discussion. ConstGeneric, + /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. + /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by + /// `body_id` is an anonymous constant and `lifetime_ref` is non-static. + AnonConst, + /// For **Modern** cases, create a new anonymous region parameter /// and reference that. /// @@ -532,7 +537,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_anon_const(&mut self, constant: &'ast AnonConst) { // We deal with repeat expressions explicitly in `resolve_expr`. - self.resolve_anon_const(constant, IsRepeatExpr::No); + self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| { + this.resolve_anon_const(constant, IsRepeatExpr::No); + }) } fn visit_expr(&mut self, expr: &'ast Expr) { self.resolve_expr(expr, None); @@ -1117,7 +1124,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.ribs[TypeNS].push(forward_ty_ban_rib); this.ribs[ValueNS].push(forward_const_ban_rib); this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { - this.visit_anon_const(expr) + this.resolve_anon_const(expr, IsRepeatExpr::No) }); forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap(); forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap(); @@ -1174,6 +1181,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error); return; } + LifetimeRibKind::AnonConst => { + self.maybe_emit_forbidden_non_static_lifetime_error(lifetime); + self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error); + return; + } _ => {} } } @@ -3076,9 +3088,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { is_repeat, constant.value.is_potential_trivial_const_param(), None, - |this| { - visit::walk_anon_const(this, constant); - }, + |this| visit::walk_anon_const(this, constant), ); } @@ -3229,7 +3239,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } ExprKind::Repeat(ref elem, ref ct) => { self.visit_expr(elem); - self.resolve_anon_const(ct, IsRepeatExpr::Yes); + self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| { + this.resolve_anon_const(ct, IsRepeatExpr::Yes) + }); + } + ExprKind::ConstBlock(ref ct) => { + self.resolve_anon_const(ct, IsRepeatExpr::No); } ExprKind::Index(ref elem, ref idx) => { self.resolve_expr(elem, Some(expr)); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b153c9f95267f..894ff0f17f8a1 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1901,6 +1901,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ) .emit(); } + + /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. + /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by + /// `body_id` is an anonymous constant and `lifetime_ref` is non-static. + crate fn maybe_emit_forbidden_non_static_lifetime_error(&self, lifetime_ref: &ast::Lifetime) { + let feature_active = self.r.session.features_untracked().generic_const_exprs; + if !feature_active { + feature_err( + &self.r.session.parse_sess, + sym::generic_const_exprs, + lifetime_ref.ident.span, + "a non-static lifetime is not allowed in a `const`", + ) + .emit(); + } + } } impl<'tcx> LifetimeContext<'_, 'tcx> { @@ -2398,32 +2414,4 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { _ => unreachable!(), } } - - /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. - /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by - /// `body_id` is an anonymous constant and `lifetime_ref` is non-static. - crate fn maybe_emit_forbidden_non_static_lifetime_error( - &self, - body_id: hir::BodyId, - lifetime_ref: &'tcx hir::Lifetime, - ) { - let is_anon_const = matches!( - self.tcx.def_kind(self.tcx.hir().body_owner_def_id(body_id)), - hir::def::DefKind::AnonConst - ); - let is_allowed_lifetime = matches!( - lifetime_ref.name, - hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore - ); - - if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime { - feature_err( - &self.tcx.sess.parse_sess, - sym::generic_const_exprs, - lifetime_ref.span, - "a non-static lifetime is not allowed in a `const`", - ) - .emit(); - } - } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 6bb0c3b5e6b59..35a40a0a32131 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -2243,10 +2243,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let result = loop { match *scope { Scope::Body { id, s } => { - // Non-static lifetimes are prohibited in anonymous constants without - // `generic_const_exprs`. - self.maybe_emit_forbidden_non_static_lifetime_error(id, lifetime_ref); - outermost_body = Some(id); scope = s; } From 7d990a8c1838a18c54a4b8a9f5fe74ea507ecbb3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 31 Mar 2022 20:11:22 +0200 Subject: [PATCH 04/11] Bless tests. --- .../const-arg-in-const-arg.min.stderr | 275 ++++++++++++++---- .../const-generics/const-arg-in-const-arg.rs | 17 +- 2 files changed, 225 insertions(+), 67 deletions(-) diff --git a/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr b/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr index ac693426fbd98..88d9ed46e1ad3 100644 --- a/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr +++ b/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -16,53 +16,8 @@ LL | let _: [u8; bar::()]; = help: const parameters may only be used as standalone arguments, i.e. `N` = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions -error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:24:23 - | -LL | let _ = [0; bar::()]; - | ^ cannot perform const operation using `N` - | - = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions - -error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:29:24 - | -LL | let _: Foo<{ foo::() }>; - | ^ cannot perform const operation using `T` - | - = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions - -error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:30:24 - | -LL | let _: Foo<{ bar::() }>; - | ^ cannot perform const operation using `N` - | - = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions - -error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:35:27 - | -LL | let _ = Foo::<{ foo::() }>; - | ^ cannot perform const operation using `T` - | - = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions - -error: generic parameters may not be used in const operations - --> $DIR/const-arg-in-const-arg.rs:36:27 - | -LL | let _ = Foo::<{ bar::() }>; - | ^ cannot perform const operation using `N` - | - = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions - error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:15:23 + --> $DIR/const-arg-in-const-arg.rs:16:23 | LL | let _: [u8; faz::<'a>(&())]; | ^^ @@ -71,7 +26,7 @@ LL | let _: [u8; faz::<'a>(&())]; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:16:23 + --> $DIR/const-arg-in-const-arg.rs:18:23 | LL | let _: [u8; baz::<'a>(&())]; | ^^ @@ -80,7 +35,7 @@ LL | let _: [u8; baz::<'a>(&())]; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:17:23 + --> $DIR/const-arg-in-const-arg.rs:19:23 | LL | let _: [u8; faz::<'b>(&())]; | ^^ @@ -89,7 +44,7 @@ LL | let _: [u8; faz::<'b>(&())]; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:18:23 + --> $DIR/const-arg-in-const-arg.rs:21:23 | LL | let _: [u8; baz::<'b>(&())]; | ^^ @@ -97,8 +52,17 @@ LL | let _: [u8; baz::<'b>(&())]; = note: see issue #76560 for more information = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:24:23 + | +LL | let _ = [0; bar::()]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:25:23 + --> $DIR/const-arg-in-const-arg.rs:26:23 | LL | let _ = [0; faz::<'a>(&())]; | ^^ @@ -107,7 +71,7 @@ LL | let _ = [0; faz::<'a>(&())]; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:26:23 + --> $DIR/const-arg-in-const-arg.rs:28:23 | LL | let _ = [0; baz::<'a>(&())]; | ^^ @@ -116,7 +80,7 @@ LL | let _ = [0; baz::<'a>(&())]; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:27:23 + --> $DIR/const-arg-in-const-arg.rs:29:23 | LL | let _ = [0; faz::<'b>(&())]; | ^^ @@ -125,7 +89,7 @@ LL | let _ = [0; faz::<'b>(&())]; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:28:23 + --> $DIR/const-arg-in-const-arg.rs:31:23 | LL | let _ = [0; baz::<'b>(&())]; | ^^ @@ -133,8 +97,26 @@ LL | let _ = [0; baz::<'b>(&())]; = note: see issue #76560 for more information = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:32:24 + | +LL | let _: Foo<{ foo::() }>; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:33:24 + | +LL | let _: Foo<{ bar::() }>; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:31:24 + --> $DIR/const-arg-in-const-arg.rs:35:24 | LL | let _: Foo<{ faz::<'a>(&()) }>; | ^^ @@ -143,7 +125,7 @@ LL | let _: Foo<{ faz::<'a>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:32:24 + --> $DIR/const-arg-in-const-arg.rs:37:24 | LL | let _: Foo<{ baz::<'a>(&()) }>; | ^^ @@ -152,7 +134,7 @@ LL | let _: Foo<{ baz::<'a>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:33:24 + --> $DIR/const-arg-in-const-arg.rs:38:24 | LL | let _: Foo<{ faz::<'b>(&()) }>; | ^^ @@ -161,7 +143,7 @@ LL | let _: Foo<{ faz::<'b>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:34:24 + --> $DIR/const-arg-in-const-arg.rs:40:24 | LL | let _: Foo<{ baz::<'b>(&()) }>; | ^^ @@ -169,8 +151,26 @@ LL | let _: Foo<{ baz::<'b>(&()) }>; = note: see issue #76560 for more information = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:41:27 + | +LL | let _ = Foo::<{ foo::() }>; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:42:27 + | +LL | let _ = Foo::<{ bar::() }>; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:37:27 + --> $DIR/const-arg-in-const-arg.rs:44:27 | LL | let _ = Foo::<{ faz::<'a>(&()) }>; | ^^ @@ -179,7 +179,7 @@ LL | let _ = Foo::<{ faz::<'a>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:38:27 + --> $DIR/const-arg-in-const-arg.rs:46:27 | LL | let _ = Foo::<{ baz::<'a>(&()) }>; | ^^ @@ -188,7 +188,7 @@ LL | let _ = Foo::<{ baz::<'a>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:39:27 + --> $DIR/const-arg-in-const-arg.rs:47:27 | LL | let _ = Foo::<{ faz::<'b>(&()) }>; | ^^ @@ -197,7 +197,7 @@ LL | let _ = Foo::<{ faz::<'b>(&()) }>; = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable error[E0658]: a non-static lifetime is not allowed in a `const` - --> $DIR/const-arg-in-const-arg.rs:40:27 + --> $DIR/const-arg-in-const-arg.rs:49:27 | LL | let _ = Foo::<{ baz::<'b>(&()) }>; | ^^ @@ -205,6 +205,155 @@ LL | let _ = Foo::<{ baz::<'b>(&()) }>; = note: see issue #76560 for more information = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable -error: aborting due to 23 previous errors +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:14:23 + | +LL | let _: [u8; bar::()]; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: [u8; bar::<{ N }>()]; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:16:23 + | +LL | let _: [u8; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:19:23 + | +LL | let _: [u8; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:24:23 + | +LL | let _ = [0; bar::()]; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _ = [0; bar::<{ N }>()]; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:26:23 + | +LL | let _ = [0; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:29:23 + | +LL | let _ = [0; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:33:24 + | +LL | let _: Foo<{ bar::() }>; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Foo<{ bar::<{ N }>() }>; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:35:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:38:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: constant expression depends on a generic parameter + --> $DIR/const-arg-in-const-arg.rs:23:17 + | +LL | let _ = [0; foo::()]; + | ^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:42:27 + | +LL | let _ = Foo::<{ bar::() }>; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _ = Foo::<{ bar::<{ N }>() }>; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:44:27 + | +LL | let _ = Foo::<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:47:27 + | +LL | let _ = Foo::<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: aborting due to 36 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0658, E0747. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-arg-in-const-arg.rs b/src/test/ui/const-generics/const-arg-in-const-arg.rs index 39f0b23733029..b9daadb547493 100644 --- a/src/test/ui/const-generics/const-arg-in-const-arg.rs +++ b/src/test/ui/const-generics/const-arg-in-const-arg.rs @@ -12,31 +12,40 @@ struct Foo; fn test<'a, 'b, T, const N: usize>() where &'b (): Sized { let _: [u8; foo::()]; //~ ERROR generic parameters may not let _: [u8; bar::()]; //~ ERROR generic parameters may not + //~^ ERROR unresolved item provided when a constant was expected let _: [u8; faz::<'a>(&())]; //~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments let _: [u8; baz::<'a>(&())]; //~ ERROR a non-static lifetime let _: [u8; faz::<'b>(&())]; //~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments let _: [u8; baz::<'b>(&())]; //~ ERROR a non-static lifetime - // NOTE: This can be a future compat warning instead of an error, - // so we stop compilation before emitting this error in this test. - let _ = [0; foo::()]; - + let _ = [0; foo::()]; //~ ERROR constant expression depends on a generic parameter let _ = [0; bar::()]; //~ ERROR generic parameters may not + //~^ ERROR unresolved item provided when a constant was expected let _ = [0; faz::<'a>(&())]; //~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments let _ = [0; baz::<'a>(&())]; //~ ERROR a non-static lifetime let _ = [0; faz::<'b>(&())]; //~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments let _ = [0; baz::<'b>(&())]; //~ ERROR a non-static lifetime let _: Foo<{ foo::() }>; //~ ERROR generic parameters may not let _: Foo<{ bar::() }>; //~ ERROR generic parameters may not + //~^ ERROR unresolved item provided when a constant was expected let _: Foo<{ faz::<'a>(&()) }>; //~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments let _: Foo<{ baz::<'a>(&()) }>; //~ ERROR a non-static lifetime let _: Foo<{ faz::<'b>(&()) }>; //~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments let _: Foo<{ baz::<'b>(&()) }>; //~ ERROR a non-static lifetime let _ = Foo::<{ foo::() }>; //~ ERROR generic parameters may not let _ = Foo::<{ bar::() }>; //~ ERROR generic parameters may not + //~^ ERROR unresolved item provided when a constant was expected let _ = Foo::<{ faz::<'a>(&()) }>; //~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments let _ = Foo::<{ baz::<'a>(&()) }>; //~ ERROR a non-static lifetime let _ = Foo::<{ faz::<'b>(&()) }>; //~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments let _ = Foo::<{ baz::<'b>(&()) }>; //~ ERROR a non-static lifetime } From 504c178d9735714afc39b4bf2834af703f6a0dd2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 1 Apr 2022 16:05:42 +0200 Subject: [PATCH 05/11] Extract AssocItem handling. --- compiler/rustc_resolve/src/late.rs | 294 +++++++++++++---------------- 1 file changed, 128 insertions(+), 166 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2bb808a720633..c88251820955c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1655,72 +1655,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { |this| { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits); - - let walk_assoc_item = - |this: &mut Self, - generics: &Generics, - kind, - item: &'ast AssocItem| { - this.with_generic_param_rib( - &generics.params, - AssocItemRibKind, - LifetimeRibKind::Generics { - parent: item.id, - span: generics.span, - kind, - }, - |this| { - visit::walk_assoc_item(this, item, AssocCtxt::Trait) - }, - ); - }; - - this.with_trait_items(items, |this| { - for item in items { - match &item.kind { - AssocItemKind::Const(_, ty, default) => { - this.visit_ty(ty); - // Only impose the restrictions of `ConstRibKind` for an - // actual constant expression in a provided default. - if let Some(expr) = default { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.with_constant_rib( - IsRepeatExpr::No, - true, - None, - |this| this.visit_expr(expr), - ); - } - } - AssocItemKind::Fn(box Fn { generics, .. }) => { - walk_assoc_item( - this, - generics, - LifetimeBinderKind::Function, - item, - ); - } - AssocItemKind::TyAlias(box TyAlias { - generics, - .. - }) => { - walk_assoc_item( - this, - generics, - LifetimeBinderKind::Item, - item, - ); - } - AssocItemKind::MacCall(_) => { - panic!("unexpanded macro in resolve!") - } - }; - } - }); + this.resolve_trait_items(items); }, ); }, @@ -1952,16 +1887,50 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } /// When evaluating a `trait` use its associated types' idents for suggestions in E0412. - fn with_trait_items( - &mut self, - trait_items: &'ast [P], - f: impl FnOnce(&mut Self) -> T, - ) -> T { + fn resolve_trait_items(&mut self, trait_items: &'ast [P]) { let trait_assoc_items = replace(&mut self.diagnostic_metadata.current_trait_assoc_items, Some(&trait_items)); - let result = f(self); + + let walk_assoc_item = + |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| { + this.with_generic_param_rib( + &generics.params, + AssocItemRibKind, + LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind }, + |this| visit::walk_assoc_item(this, item, AssocCtxt::Trait), + ); + }; + + for item in trait_items { + match &item.kind { + AssocItemKind::Const(_, ty, default) => { + self.visit_ty(ty); + // Only impose the restrictions of `ConstRibKind` for an + // actual constant expression in a provided default. + if let Some(expr) = default { + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + self.with_constant_rib(IsRepeatExpr::No, true, None, |this| { + this.visit_expr(expr) + }); + } + } + AssocItemKind::Fn(box Fn { generics, .. }) => { + walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); + } + AssocItemKind::TyAlias(box TyAlias { generics, .. }) => { + walk_assoc_item(self, generics, LifetimeBinderKind::Item, item); + } + AssocItemKind::MacCall(_) => { + panic!("unexpanded macro in resolve!") + } + }; + } + self.diagnostic_metadata.current_trait_assoc_items = trait_assoc_items; - result } /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). @@ -2048,99 +2017,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); for item in impl_items { - use crate::ResolutionError::*; - match &item.kind { - AssocItemKind::Const(_default, _ty, _expr) => { - debug!("resolve_implementation AssocItemKind::Const"); - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - |i, s, c| ConstNotMemberOfTrait(i, s, c), - ); - - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.with_constant_rib( - IsRepeatExpr::No, - true, - None, - |this| { - visit::walk_assoc_item( - this, - item, - AssocCtxt::Impl, - ) - }, - ); - } - AssocItemKind::Fn(box Fn { generics, .. }) => { - debug!("resolve_implementation AssocItemKind::Fn"); - // We also need a new scope for the impl item type parameters. - this.with_generic_param_rib( - &generics.params, - AssocItemRibKind, - LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind: LifetimeBinderKind::Function }, - |this| { - // If this is a trait impl, ensure the method - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - |i, s, c| MethodNotMemberOfTrait(i, s, c), - ); - - visit::walk_assoc_item( - this, - item, - AssocCtxt::Impl, - ) - }, - ); - } - AssocItemKind::TyAlias(box TyAlias { - generics, .. - }) => { - debug!("resolve_implementation AssocItemKind::TyAlias"); - // We also need a new scope for the impl item type parameters. - this.with_generic_param_rib( - &generics.params, - AssocItemRibKind, - LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind: LifetimeBinderKind::Item }, - |this| { - // If this is a trait impl, ensure the type - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - TypeNS, - item.span, - |i, s, c| TypeNotMemberOfTrait(i, s, c), - ); - - visit::walk_assoc_item( - this, - item, - AssocCtxt::Impl, - ) - }, - ); - } - AssocItemKind::MacCall(_) => { - panic!("unexpanded macro in resolve!") - } - } + this.resolve_impl_item(&**item); } }); }); @@ -2153,6 +2030,91 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }); } + fn resolve_impl_item(&mut self, item: &'ast AssocItem) { + use crate::ResolutionError::*; + match &item.kind { + AssocItemKind::Const(_default, _ty, _expr) => { + debug!("resolve_implementation AssocItemKind::Const"); + // If this is a trait impl, ensure the const + // exists in trait + self.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + |i, s, c| ConstNotMemberOfTrait(i, s, c), + ); + + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + self.with_constant_rib(IsRepeatExpr::No, true, None, |this| { + visit::walk_assoc_item(this, item, AssocCtxt::Impl) + }); + } + AssocItemKind::Fn(box Fn { generics, .. }) => { + debug!("resolve_implementation AssocItemKind::Fn"); + // We also need a new scope for the impl item type parameters. + self.with_generic_param_rib( + &generics.params, + AssocItemRibKind, + LifetimeRibKind::Generics { + parent: item.id, + span: generics.span, + kind: LifetimeBinderKind::Function, + }, + |this| { + // If this is a trait impl, ensure the method + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + |i, s, c| MethodNotMemberOfTrait(i, s, c), + ); + + visit::walk_assoc_item(this, item, AssocCtxt::Impl) + }, + ); + } + AssocItemKind::TyAlias(box TyAlias { generics, .. }) => { + debug!("resolve_implementation AssocItemKind::TyAlias"); + // We also need a new scope for the impl item type parameters. + self.with_generic_param_rib( + &generics.params, + AssocItemRibKind, + LifetimeRibKind::Generics { + parent: item.id, + span: generics.span, + kind: LifetimeBinderKind::Item, + }, + |this| { + // If this is a trait impl, ensure the type + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + TypeNS, + item.span, + |i, s, c| TypeNotMemberOfTrait(i, s, c), + ); + + visit::walk_assoc_item(this, item, AssocCtxt::Impl) + }, + ); + } + AssocItemKind::MacCall(_) => { + panic!("unexpanded macro in resolve!") + } + } + } + fn check_trait_item( &mut self, id: NodeId, From dbc04f3bb82b9ecf1669dfd39c64f2d02deac188 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 18 Apr 2022 15:18:23 +0200 Subject: [PATCH 06/11] Separate named and anonymous lifetime ribs. --- compiler/rustc_resolve/src/late.rs | 289 ++++++++++++++++------------- 1 file changed, 155 insertions(+), 134 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c88251820955c..644053af1cfcf 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -208,23 +208,6 @@ enum LifetimeRibKind { /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by /// `body_id` is an anonymous constant and `lifetime_ref` is non-static. AnonConst, - - /// For **Modern** cases, create a new anonymous region parameter - /// and reference that. - /// - /// For **Dyn Bound** cases, pass responsibility to - /// `resolve_lifetime` code. - /// - /// For **Deprecated** cases, report an error. - AnonymousCreateParameter(NodeId), - - /// Give a hard error when either `&` or `'_` is written. Used to - /// rule out things like `where T: Foo<'_>`. Does not imply an - /// error on default object bounds (e.g., `Box`). - AnonymousReportError, - - /// Pass responsibility to `resolve_lifetime` code for all cases. - AnonymousPassThrough(NodeId), } #[derive(Copy, Clone, Debug)] @@ -264,6 +247,29 @@ impl LifetimeRib { } } +#[derive(Copy, Clone, Debug)] +enum AnonymousLifetimeRib { + /// This rib acts as a barrier to forbid reference to lifetimes of a parent item. + Item, + + /// For **Modern** cases, create a new anonymous region parameter + /// and reference that. + /// + /// For **Dyn Bound** cases, pass responsibility to + /// `resolve_lifetime` code. + /// + /// For **Deprecated** cases, report an error. + CreateParameter(NodeId), + + /// Give a hard error when either `&` or `'_` is written. Used to + /// rule out things like `where T: Foo<'_>`. Does not imply an + /// error on default object bounds (e.g., `Box`). + ReportError, + + /// Pass responsibility to `resolve_lifetime` code for all cases. + PassThrough(NodeId), +} + #[derive(Copy, Clone, PartialEq, Eq, Debug)] crate enum AliasPossibility { No, @@ -501,6 +507,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast> { /// The current set of local scopes for lifetimes. lifetime_ribs: Vec, + /// The current set of local scopes for anonymous lifetimes. + anonymous_lifetime_ribs: Vec, + /// The trait that the current context can refer to. current_trait_ref: Option<(Module<'a>, TraitRef)>, @@ -525,7 +534,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item)); // Always report errors in items we just entered. let old_ignore = replace(&mut self.in_func_body, false); - self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item)); + self.with_lifetime_rib(LifetimeRibKind::Item, |this| { + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Item, |this| this.resolve_item(item)) + }); self.in_func_body = old_ignore; self.diagnostic_metadata.current_item = prev; } @@ -542,7 +553,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { }) } fn visit_expr(&mut self, expr: &'ast Expr) { - self.resolve_expr(expr, None); + self.with_anon_lifetime_rib(AnonymousLifetimeRib::PassThrough(expr.id), |this| { + this.resolve_expr(expr, None); + }) } fn visit_local(&mut self, local: &'ast Local) { let local_spans = match local.pat.kind { @@ -602,8 +615,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { span, }, |this| { - this.with_lifetime_rib( - LifetimeRibKind::AnonymousPassThrough(ty.id), + this.with_anon_lifetime_rib( + AnonymousLifetimeRib::PassThrough(ty.id), |this| { this.visit_generic_param_vec(&bare_fn.generic_params, false); visit::walk_fn_decl(this, &bare_fn.decl); @@ -647,30 +660,34 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { match foreign_item.kind { ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_lifetime_rib(LifetimeRibKind::Item, |this| { - this.with_generic_param_rib( - &generics.params, - ItemRibKind(HasGenericParams::Yes), - LifetimeRibKind::Generics { - parent: foreign_item.id, - kind: LifetimeBinderKind::Item, - span: generics.span, - }, - |this| visit::walk_foreign_item(this, foreign_item), - ) + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Item, |this| { + this.with_generic_param_rib( + &generics.params, + ItemRibKind(HasGenericParams::Yes), + LifetimeRibKind::Generics { + parent: foreign_item.id, + kind: LifetimeBinderKind::Item, + span: generics.span, + }, + |this| visit::walk_foreign_item(this, foreign_item), + ) + }) }); } ForeignItemKind::Fn(box Fn { ref generics, .. }) => { self.with_lifetime_rib(LifetimeRibKind::Item, |this| { - this.with_generic_param_rib( - &generics.params, - ItemRibKind(HasGenericParams::Yes), - LifetimeRibKind::Generics { - parent: foreign_item.id, - kind: LifetimeBinderKind::Function, - span: generics.span, - }, - |this| visit::walk_foreign_item(this, foreign_item), - ) + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Item, |this| { + this.with_generic_param_rib( + &generics.params, + ItemRibKind(HasGenericParams::Yes), + LifetimeRibKind::Generics { + parent: foreign_item.id, + kind: LifetimeBinderKind::Function, + span: generics.span, + }, + |this| visit::walk_foreign_item(this, foreign_item), + ) + }) }); } ForeignItemKind::Static(..) => { @@ -689,7 +706,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // a body, or if there's no body for some other reason. FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) | FnKind::Fn(_, _, sig, _, generics, None) => { - self.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| { + self.with_anon_lifetime_rib(AnonymousLifetimeRib::PassThrough(fn_id), |this| { // We don't need to deal with patterns in parameters, because // they are not possible for foreign or bodiless functions. this.visit_fn_header(&sig.header); @@ -723,8 +740,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // In `async fn`, argument-position elided lifetimes // must be transformed into fresh generic parameters so that // they can be applied to the opaque `impl Trait` return type. - this.with_lifetime_rib( - LifetimeRibKind::AnonymousCreateParameter(fn_id), + this.with_anon_lifetime_rib( + AnonymousLifetimeRib::CreateParameter(fn_id), |this| { // Add each argument to the rib. this.resolve_params(&declaration.inputs) @@ -743,9 +760,14 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { .iter() .map(|(&ident, &(node_id, res))| (ident, node_id, res)), ); - match rib.kind { - LifetimeRibKind::Item => break, - LifetimeRibKind::AnonymousCreateParameter(id) => { + if let LifetimeRibKind::Item = rib.kind { + break; + } + } + for rib in this.anonymous_lifetime_ribs.iter().rev() { + match rib { + AnonymousLifetimeRib::Item => break, + AnonymousLifetimeRib::CreateParameter(id) => { if let Some(earlier_fresh) = this.r.extra_lifetime_params_map.get(&id) { @@ -757,12 +779,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); - this.with_lifetime_rib( - LifetimeRibKind::AnonymousPassThrough(async_node_id), + this.with_anon_lifetime_rib( + AnonymousLifetimeRib::PassThrough(async_node_id), |this| visit::walk_fn_ret_ty(this, &declaration.output), ); } else { - this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| { + this.with_anon_lifetime_rib(AnonymousLifetimeRib::PassThrough(fn_id), |this| { // Add each argument to the rib. this.resolve_params(&declaration.inputs); @@ -774,7 +796,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // Be sure not to set this until the function signature has been resolved. let previous_state = replace(&mut this.in_func_body, true); // Resolve the function body, potentially inside the body of an async closure - this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| { + this.with_anon_lifetime_rib(AnonymousLifetimeRib::PassThrough(fn_id), |this| { match fn_kind { FnKind::Fn(.., body) => walk_list!(this, visit_block, body), FnKind::Closure(_, body) => this.visit_expr(body), @@ -858,8 +880,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { if let Some(ref args) = path_segment.args { match &**args { GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args), - GenericArgs::Parenthesized(..) => self.with_lifetime_rib( - LifetimeRibKind::AnonymousPassThrough(path_segment.id), + GenericArgs::Parenthesized(..) => self.with_anon_lifetime_rib( + AnonymousLifetimeRib::PassThrough(path_segment.id), |this| visit::walk_generic_args(this, path_span, args), ), } @@ -870,7 +892,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { debug!("visit_where_predicate {:?}", p); let previous_value = replace(&mut self.diagnostic_metadata.current_where_predicate, Some(p)); - self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { + self.with_anon_lifetime_rib(AnonymousLifetimeRib::ReportError, |this| { if let WherePredicate::BoundPredicate(WhereBoundPredicate { ref bounded_ty, ref bounds, @@ -942,6 +964,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }, label_ribs: Vec::new(), lifetime_ribs: Vec::new(), + anonymous_lifetime_ribs: vec![AnonymousLifetimeRib::Item], current_trait_ref: None, diagnostic_metadata: DiagnosticMetadata::default(), // errors at module scope should always be reported @@ -1082,7 +1105,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } - self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { + self.with_anon_lifetime_rib(AnonymousLifetimeRib::ReportError, |this| { for param in params { match param.kind { GenericParamKind::Lifetime => { @@ -1204,56 +1227,55 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.record_lifetime_res(lifetime.id, LifetimeRes::Error); } + #[tracing::instrument(level = "debug", skip(self, work))] + fn with_anon_lifetime_rib( + &mut self, + rib: AnonymousLifetimeRib, + work: impl FnOnce(&mut Self) -> T, + ) -> T { + self.anonymous_lifetime_ribs.push(rib); + let ret = work(self); + self.anonymous_lifetime_ribs.pop(); + ret + } + #[tracing::instrument(level = "debug", skip(self))] fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); - for i in (0..self.lifetime_ribs.len()).rev() { - let rib = &mut self.lifetime_ribs[i]; - match rib.kind { - LifetimeRibKind::AnonymousCreateParameter(item_node_id) => { - self.create_fresh_lifetime(lifetime.id, lifetime.ident, item_node_id); - return; - } - LifetimeRibKind::AnonymousReportError => { - let (msg, note) = if elided { - ( - "`&` without an explicit lifetime name cannot be used here", - "explicit lifetime name needed here", - ) - } else { - ("`'_` cannot be used here", "`'_` is a reserved lifetime name") - }; - rustc_errors::struct_span_err!( - self.r.session, - lifetime.ident.span, - E0637, - "{}", - msg, + let res = match *self.anonymous_lifetime_ribs.last().unwrap() { + AnonymousLifetimeRib::CreateParameter(item_node_id) => { + self.create_fresh_lifetime(lifetime.id, lifetime.ident, item_node_id) + } + AnonymousLifetimeRib::ReportError => { + let (msg, note) = if elided { + ( + "`&` without an explicit lifetime name cannot be used here", + "explicit lifetime name needed here", ) - .span_label(lifetime.ident.span, note) - .emit(); + } else { + ("`'_` cannot be used here", "`'_` is a reserved lifetime name") + }; + rustc_errors::struct_span_err!( + self.r.session, + lifetime.ident.span, + E0637, + "{}", + msg, + ) + .span_label(lifetime.ident.span, note) + .emit(); - self.record_lifetime_res(lifetime.id, LifetimeRes::Error); - return; - } - LifetimeRibKind::AnonymousPassThrough(node_id) => { - self.record_lifetime_res( - lifetime.id, - LifetimeRes::Anonymous { binder: node_id, elided }, - ); - return; - } - LifetimeRibKind::Item => break, - _ => {} + LifetimeRes::Error } - } - // This resolution is wrong, it passes the work to HIR lifetime resolution. - // We cannot use `LifetimeRes::Error` because we do not emit a diagnostic. - self.record_lifetime_res( - lifetime.id, - LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided }, - ); + AnonymousLifetimeRib::PassThrough(node_id) => { + LifetimeRes::Anonymous { binder: node_id, elided } + } + // This resolution is wrong, it passes the work to HIR lifetime resolution. + // We cannot use `LifetimeRes::Error` because we do not emit a diagnostic. + AnonymousLifetimeRib::Item => LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided }, + }; + self.record_lifetime_res(lifetime.id, res); } #[tracing::instrument(level = "debug", skip(self))] @@ -1269,7 +1291,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } #[tracing::instrument(level = "debug", skip(self))] - fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, item_node_id: NodeId) { + fn create_fresh_lifetime( + &mut self, + id: NodeId, + ident: Ident, + item_node_id: NodeId, + ) -> LifetimeRes { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); debug!(?ident.span); let item_def_id = self.r.local_def_id(item_node_id); @@ -1284,12 +1311,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { debug!(?def_id); let region = LifetimeRes::Fresh { param: def_id, binder: item_node_id }; - self.record_lifetime_res(id, region); self.r.extra_lifetime_params_map.entry(item_node_id).or_insert_with(Vec::new).push(( ident, def_node_id, region, )); + region } #[tracing::instrument(level = "debug", skip(self))] @@ -1346,38 +1373,30 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { | PathSource::Struct | PathSource::TupleStruct(..) => false, }; - let mut res = LifetimeRes::Error; - for rib in self.lifetime_ribs.iter().rev() { - match rib.kind { - // In create-parameter mode we error here because we don't want to support - // deprecated impl elision in new features like impl elision and `async fn`, - // both of which work using the `CreateParameter` mode: - // - // impl Foo for std::cell::Ref // note lack of '_ - // async fn foo(_: std::cell::Ref) { ... } - LifetimeRibKind::AnonymousCreateParameter(_) => { - break; - } - // `PassThrough` is the normal case. - // `new_error_lifetime`, which would usually be used in the case of `ReportError`, - // is unsuitable here, as these can occur from missing lifetime parameters in a - // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit - // lifetime. Instead, we simply create an implicit lifetime, which will be checked - // later, at which point a suitable error will be emitted. - LifetimeRibKind::AnonymousPassThrough(binder) => { - res = LifetimeRes::Anonymous { binder, elided: true }; - break; - } - LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => { - // FIXME(cjgillot) This resolution is wrong, but this does not matter - // since these cases are erroneous anyway. Lifetime resolution should - // emit a "missing lifetime specifier" diagnostic. - res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true }; - break; - } - _ => {} + let res = match self.anonymous_lifetime_ribs.last().unwrap() { + // In create-parameter mode we error here because we don't want to support + // deprecated impl elision in new features like impl elision and `async fn`, + // both of which work using the `CreateParameter` mode: + // + // impl Foo for std::cell::Ref // note lack of '_ + // async fn foo(_: std::cell::Ref) { ... } + AnonymousLifetimeRib::CreateParameter(_) => LifetimeRes::Error, + // `PassThrough` is the normal case. + // `new_error_lifetime`, which would usually be used in the case of `ReportError`, + // is unsuitable here, as these can occur from missing lifetime parameters in a + // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit + // lifetime. Instead, we simply create an implicit lifetime, which will be checked + // later, at which point a suitable error will be emitted. + AnonymousLifetimeRib::PassThrough(binder) => { + LifetimeRes::Anonymous { binder: *binder, elided: true } } - } + // FIXME(cjgillot) This resolution is wrong, but this does not matter + // since these cases are erroneous anyway. Lifetime resolution should + // emit a "missing lifetime specifier" diagnostic. + AnonymousLifetimeRib::ReportError | AnonymousLifetimeRib::Item => { + LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true } + } + }; let node_ids = self.r.next_node_ids(expected_lifetimes); self.record_lifetime_res( @@ -1838,7 +1857,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) { let kind = ItemRibKind(HasGenericParams::No); self.with_lifetime_rib(LifetimeRibKind::Item, |this| { - this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Item, |this| { + this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) + }) }) } @@ -1987,7 +2008,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, parent: item_id, kind: LifetimeBinderKind::ImplBlock }, |this| { // Dummy self type for better errors if `Self` is used in the trait path. this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| { - this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter(item_id), |this| { + this.with_anon_lifetime_rib(AnonymousLifetimeRib::CreateParameter(item_id), |this| { // Resolve the trait reference, if necessary. this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { let item_def_id = this.r.local_def_id(item_id); @@ -2011,7 +2032,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.visit_generics(generics); // Resolve the items within the impl. - this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(item_id), + this.with_anon_lifetime_rib(AnonymousLifetimeRib::PassThrough(item_id), |this| { this.with_current_self_type(self_type, |this| { this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { From db3845da6bb4715382b0d79ab5befaa647f29e3b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 18 Apr 2022 17:51:39 +0200 Subject: [PATCH 07/11] Introduce AnonymousLifetimeRib::Static. --- compiler/rustc_resolve/src/late.rs | 57 +++++++++++++++++++----------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 644053af1cfcf..9256a60442a72 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -252,6 +252,9 @@ enum AnonymousLifetimeRib { /// This rib acts as a barrier to forbid reference to lifetimes of a parent item. Item, + /// Replace all lifetimes by `'static`. + Static, + /// For **Modern** cases, create a new anonymous region parameter /// and reference that. /// @@ -549,7 +552,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { fn visit_anon_const(&mut self, constant: &'ast AnonConst) { // We deal with repeat expressions explicitly in `resolve_expr`. self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| { - this.resolve_anon_const(constant, IsRepeatExpr::No); + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Static, |this| { + this.resolve_anon_const(constant, IsRepeatExpr::No); + }) }) } fn visit_expr(&mut self, expr: &'ast Expr) { @@ -692,7 +697,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } ForeignItemKind::Static(..) => { self.with_item_rib(|this| { - visit::walk_foreign_item(this, foreign_item); + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Static, |this| { + visit::walk_foreign_item(this, foreign_item); + }) }); } ForeignItemKind::MacCall(..) => { @@ -1271,6 +1278,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { AnonymousLifetimeRib::PassThrough(node_id) => { LifetimeRes::Anonymous { binder: node_id, elided } } + AnonymousLifetimeRib::Static => LifetimeRes::Static, // This resolution is wrong, it passes the work to HIR lifetime resolution. // We cannot use `LifetimeRes::Error` because we do not emit a diagnostic. AnonymousLifetimeRib::Item => LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided }, @@ -1396,6 +1404,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { AnonymousLifetimeRib::ReportError | AnonymousLifetimeRib::Item => { LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true } } + AnonymousLifetimeRib::Static => LifetimeRes::Static, }; let node_ids = self.r.next_node_ids(expected_lifetimes); @@ -1712,7 +1721,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => { self.with_item_rib(|this| { - this.visit_ty(ty); + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Static, |this| { + this.visit_ty(ty) + }); if let Some(expr) = expr { let constant_item_kind = match item.kind { ItemKind::Const(..) => ConstantItemKind::Const, @@ -2056,24 +2067,26 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { match &item.kind { AssocItemKind::Const(_default, _ty, _expr) => { debug!("resolve_implementation AssocItemKind::Const"); - // If this is a trait impl, ensure the const - // exists in trait - self.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - |i, s, c| ConstNotMemberOfTrait(i, s, c), - ); + self.with_anon_lifetime_rib(AnonymousLifetimeRib::Static, |this| { + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + |i, s, c| ConstNotMemberOfTrait(i, s, c), + ); - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - self.with_constant_rib(IsRepeatExpr::No, true, None, |this| { - visit::walk_assoc_item(this, item, AssocCtxt::Impl) + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.with_constant_rib(IsRepeatExpr::No, true, None, |this| { + visit::walk_assoc_item(this, item, AssocCtxt::Impl) + }) }); } AssocItemKind::Fn(box Fn { generics, .. }) => { @@ -3224,7 +3237,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ExprKind::Repeat(ref elem, ref ct) => { self.visit_expr(elem); self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| { - this.resolve_anon_const(ct, IsRepeatExpr::Yes) + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Static, |this| { + this.resolve_anon_const(ct, IsRepeatExpr::Yes) + }) }); } ExprKind::ConstBlock(ref ct) => { From 36f3cd77736a02b8a97b48769edb3dee15b71b31 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 17 Apr 2022 18:39:25 +0200 Subject: [PATCH 08/11] Report elision failures on the AST. --- compiler/rustc_resolve/src/late.rs | 643 +++++++++++----- .../rustc_resolve/src/late/diagnostics.rs | 684 +++++------------- compiler/rustc_resolve/src/late/lifetimes.rs | 191 +---- compiler/rustc_resolve/src/lib.rs | 1 + 4 files changed, 675 insertions(+), 844 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9256a60442a72..5089a53315765 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -271,6 +271,40 @@ enum AnonymousLifetimeRib { /// Pass responsibility to `resolve_lifetime` code for all cases. PassThrough(NodeId), + + /// Record anonymous lifetimes as this one. + Elided(NodeId, Option), +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +struct MissingLifetime { + span: Span, + kind: MissingLifetimeKind, + count: usize, +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +enum MissingLifetimeKind { + /// An explicit `'_`. + Underscore, + /// An elided lifetime `&' ty`. + Ampersand, + /// An elided lifetime in brackets with written brackets. + Comma, + /// An elided lifetime with elided brackets. + Brackets, +} + +#[derive(Clone, Debug)] +struct ElisionFailureInfo { + /// The index of the argument in the original definition. + index: usize, + /// The name of the argument if it's a simple ident. + ident: Option, + /// The number of lifetimes in the parameter. + lifetime_count: usize, + /// The span of the parameter. + span: Span, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -492,6 +526,8 @@ struct DiagnosticMetadata<'ast> { current_where_predicate: Option<&'ast WherePredicate>, current_type_path: Option<&'ast Ty>, + + current_elision_failures: Vec, } struct LateResolutionVisitor<'a, 'b, 'ast> { @@ -513,6 +549,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast> { /// The current set of local scopes for anonymous lifetimes. anonymous_lifetime_ribs: Vec, + /// We are looking for lifetimes in an elision context. + lifetime_elision_candidates: Option>, + /// The trait that the current context can refer to. current_trait_ref: Option<(Module<'a>, TraitRef)>, @@ -583,12 +622,15 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { TyKind::Rptr(None, _) => { // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with // NodeId `ty.id`. + // This span will be used in case of elision failure. let span = self.r.session.source_map().next_point(ty.span.shrink_to_lo()); self.resolve_elided_lifetime(ty.id, span); + visit::walk_ty(self, ty) } TyKind::Path(ref qself, ref path) => { self.diagnostic_metadata.current_type_path = Some(ty); self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); + visit::walk_ty(self, ty) } TyKind::ImplicitSelf => { let self_ty = Ident::with_dummy_span(kw::SelfUpper); @@ -601,9 +643,22 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { ) .map_or(Res::Err, |d| d.res()); self.r.record_partial_res(ty.id, PartialRes::new(res)); + visit::walk_ty(self, ty) } TyKind::TraitObject(ref bounds, ..) => { self.diagnostic_metadata.current_trait_object = Some(&bounds[..]); + visit::walk_ty(self, ty) + } + TyKind::ImplTrait(..) => { + if let AnonymousLifetimeRib::PassThrough(_) = + self.anonymous_lifetime_ribs.last().unwrap() + { + self.with_anon_lifetime_rib(AnonymousLifetimeRib::ReportError, |this| { + visit::walk_ty(this, ty) + }); + } else { + visit::walk_ty(self, ty) + } } TyKind::BareFn(ref bare_fn) => { let span = if bare_fn.generic_params.is_empty() { @@ -620,21 +675,21 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { span, }, |this| { - this.with_anon_lifetime_rib( - AnonymousLifetimeRib::PassThrough(ty.id), - |this| { - this.visit_generic_param_vec(&bare_fn.generic_params, false); - visit::walk_fn_decl(this, &bare_fn.decl); - }, + this.visit_generic_param_vec(&bare_fn.generic_params, false); + this.resolve_fn_like_elision( + ty.id, + None, + false, + // We don't need to deal with patterns in parameters, because + // they are not possible for foreign or bodiless functions. + bare_fn.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), + &bare_fn.decl.output, ); }, - ); - self.diagnostic_metadata.current_trait_object = prev; - return; + ) } - _ => (), + _ => visit::walk_ty(self, ty), } - visit::walk_ty(self, ty); self.diagnostic_metadata.current_trait_object = prev; self.diagnostic_metadata.current_type_path = prev_ty; } @@ -713,13 +768,14 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // a body, or if there's no body for some other reason. FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) | FnKind::Fn(_, _, sig, _, generics, None) => { - self.with_anon_lifetime_rib(AnonymousLifetimeRib::PassThrough(fn_id), |this| { - // We don't need to deal with patterns in parameters, because - // they are not possible for foreign or bodiless functions. - this.visit_fn_header(&sig.header); - this.visit_generics(generics); - visit::walk_fn_decl(this, &sig.decl); - }); + self.visit_generics(generics); + self.resolve_fn_like_elision( + fn_id, + None, + sig.decl.has_self(), + sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), + &sig.decl.output, + ); return; } FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind, @@ -739,65 +795,36 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { this.with_label_rib(rib_kind, |this| { let async_node_id = fn_kind.header().and_then(|h| h.asyncness.opt_return_id()); - if let FnKind::Fn(_, _, _, _, generics, _) = fn_kind { - this.visit_generics(generics); - } + match fn_kind { + FnKind::Fn(_, _, _, _, generics, _) => { + this.visit_generics(generics); - if let Some(async_node_id) = async_node_id { - // In `async fn`, argument-position elided lifetimes - // must be transformed into fresh generic parameters so that - // they can be applied to the opaque `impl Trait` return type. - this.with_anon_lifetime_rib( - AnonymousLifetimeRib::CreateParameter(fn_id), - |this| { - // Add each argument to the rib. - this.resolve_params(&declaration.inputs) - }, - ); - - // Construct the list of in-scope lifetime parameters for async lowering. - // We include all lifetime parameters, either named or "Fresh". - // The order of those parameters does not matter, as long as it is - // deterministic. - let mut extra_lifetime_params = - this.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default(); - for rib in this.lifetime_ribs.iter().rev() { - extra_lifetime_params.extend( - rib.bindings + this.resolve_fn_like_elision( + fn_id, + async_node_id, + declaration.has_self(), + declaration + .inputs .iter() - .map(|(&ident, &(node_id, res))| (ident, node_id, res)), + .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)), + &declaration.output, ); - if let LifetimeRibKind::Item = rib.kind { - break; - } } - for rib in this.anonymous_lifetime_ribs.iter().rev() { - match rib { - AnonymousLifetimeRib::Item => break, - AnonymousLifetimeRib::CreateParameter(id) => { - if let Some(earlier_fresh) = - this.r.extra_lifetime_params_map.get(&id) - { - extra_lifetime_params.extend(earlier_fresh); - } - } - _ => {} - } + FnKind::Closure(..) => { + let rib_kind = if async_node_id.is_some() { + AnonymousLifetimeRib::CreateParameter(fn_id) + } else { + AnonymousLifetimeRib::PassThrough(fn_id) + }; + this.with_anon_lifetime_rib(rib_kind, |this| { + this.resolve_params(&declaration.inputs) + }); + this.with_anon_lifetime_rib( + AnonymousLifetimeRib::PassThrough(fn_id), + |this| visit::walk_fn_ret_ty(this, &declaration.output), + ); } - this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); - - this.with_anon_lifetime_rib( - AnonymousLifetimeRib::PassThrough(async_node_id), - |this| visit::walk_fn_ret_ty(this, &declaration.output), - ); - } else { - this.with_anon_lifetime_rib(AnonymousLifetimeRib::PassThrough(fn_id), |this| { - // Add each argument to the rib. - this.resolve_params(&declaration.inputs); - - visit::walk_fn_ret_ty(this, &declaration.output); - }); - }; + } // Ignore errors in function bodies if this is rustdoc // Be sure not to set this until the function signature has been resolved. @@ -887,9 +914,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { if let Some(ref args) = path_segment.args { match &**args { GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args), - GenericArgs::Parenthesized(..) => self.with_anon_lifetime_rib( - AnonymousLifetimeRib::PassThrough(path_segment.id), - |this| visit::walk_generic_args(this, path_span, args), + GenericArgs::Parenthesized(args) => self.resolve_fn_like_elision( + path_segment.id, + None, + false, + args.inputs.iter().map(|ty| (None, &**ty)), + &args.output, ), } } @@ -972,6 +1002,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { label_ribs: Vec::new(), lifetime_ribs: Vec::new(), anonymous_lifetime_ribs: vec![AnonymousLifetimeRib::Item], + lifetime_elision_candidates: None, current_trait_ref: None, diagnostic_metadata: DiagnosticMetadata::default(), // errors at module scope should always be reported @@ -1177,7 +1208,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { work: impl FnOnce(&mut Self) -> T, ) -> T { self.lifetime_ribs.push(LifetimeRib::new(kind)); + let outer_elision_candidates = self.lifetime_elision_candidates.take(); let ret = work(self); + self.lifetime_elision_candidates = outer_elision_candidates; self.lifetime_ribs.pop(); ret } @@ -1187,7 +1220,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let ident = lifetime.ident; if ident.name == kw::StaticLifetime { - self.record_lifetime_res(lifetime.id, LifetimeRes::Static); + self.record_lifetime_res(lifetime.id, lifetime.ident, LifetimeRes::Static); return; } @@ -1200,7 +1233,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let rib = &self.lifetime_ribs[i]; let normalized_ident = ident.normalize_to_macros_2_0(); if let Some(&(_, region)) = rib.bindings.get(&normalized_ident) { - self.record_lifetime_res(lifetime.id, region); + self.record_lifetime_res(lifetime.id, lifetime.ident, region); return; } @@ -1231,7 +1264,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } self.emit_undeclared_lifetime_error(lifetime, outer_res); - self.record_lifetime_res(lifetime.id, LifetimeRes::Error); + self.record_lifetime_res(lifetime.id, lifetime.ident, LifetimeRes::Error); } #[tracing::instrument(level = "debug", skip(self, work))] @@ -1241,8 +1274,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { work: impl FnOnce(&mut Self) -> T, ) -> T { self.anonymous_lifetime_ribs.push(rib); + let outer_elision_candidates = self.lifetime_elision_candidates.take(); let ret = work(self); self.anonymous_lifetime_ribs.pop(); + self.lifetime_elision_candidates = outer_elision_candidates; ret } @@ -1275,26 +1310,54 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { LifetimeRes::Error } + AnonymousLifetimeRib::Elided(node_id, Some(_)) => { + LifetimeRes::Anonymous { binder: node_id, elided } + } AnonymousLifetimeRib::PassThrough(node_id) => { LifetimeRes::Anonymous { binder: node_id, elided } } + AnonymousLifetimeRib::Elided(_, None) => { + self.diagnostic_metadata.current_elision_failures.push(MissingLifetime { + span: lifetime.ident.span, + kind: if elided { + MissingLifetimeKind::Ampersand + } else { + MissingLifetimeKind::Underscore + }, + count: 1, + }); + LifetimeRes::Error + } AnonymousLifetimeRib::Static => LifetimeRes::Static, - // This resolution is wrong, it passes the work to HIR lifetime resolution. - // We cannot use `LifetimeRes::Error` because we do not emit a diagnostic. - AnonymousLifetimeRib::Item => LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided }, + AnonymousLifetimeRib::Item => { + self.report_missing_lifetime_specifiers( + vec![MissingLifetime { + span: lifetime.ident.span, + kind: if elided { + MissingLifetimeKind::Ampersand + } else { + MissingLifetimeKind::Underscore + }, + count: 1, + }], + None, + ); + LifetimeRes::Error + } }; - self.record_lifetime_res(lifetime.id, res); + self.record_lifetime_res(lifetime.id, lifetime.ident, res); } #[tracing::instrument(level = "debug", skip(self))] fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) { let id = self.r.next_node_id(); + let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) }; + self.record_lifetime_res( anchor_id, + lt.ident, LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) }, ); - - let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) }; self.resolve_anonymous_lifetime(<, true); } @@ -1374,81 +1437,109 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { continue; } - let missing = match source { - PathSource::Trait(..) | PathSource::TraitItem(..) | PathSource::Type => true, - PathSource::Expr(..) - | PathSource::Pat - | PathSource::Struct - | PathSource::TupleStruct(..) => false, + let elided_lifetime_span = if segment.has_generic_args { + // If there are brackets, but not generic arguments, then use the opening bracket + segment.args_span.with_hi(segment.args_span.lo() + BytePos(1)) + } else { + // If there are no brackets, use the identifier span. + // HACK: we use find_ancestor_inside to properly suggest elided spans in paths + // originating from macros, since the segment's span might be from a macro arg. + segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span) }; - let res = match self.anonymous_lifetime_ribs.last().unwrap() { + + let (lint, res) = match *self.anonymous_lifetime_ribs.last().unwrap() { // In create-parameter mode we error here because we don't want to support // deprecated impl elision in new features like impl elision and `async fn`, // both of which work using the `CreateParameter` mode: // // impl Foo for std::cell::Ref // note lack of '_ // async fn foo(_: std::cell::Ref) { ... } - AnonymousLifetimeRib::CreateParameter(_) => LifetimeRes::Error, + AnonymousLifetimeRib::CreateParameter(..) => { + let sess = self.r.session; + let mut err = rustc_errors::struct_span_err!( + sess, + path_span, + E0726, + "implicit elided lifetime not allowed here" + ); + rustc_errors::add_elided_lifetime_in_path_suggestion( + sess.source_map(), + &mut err, + expected_lifetimes, + path_span, + !segment.has_generic_args, + elided_lifetime_span, + ); + err.note("assuming a `'static` lifetime..."); + err.emit(); + (false, LifetimeRes::Error) + } // `PassThrough` is the normal case. // `new_error_lifetime`, which would usually be used in the case of `ReportError`, // is unsuitable here, as these can occur from missing lifetime parameters in a // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit // lifetime. Instead, we simply create an implicit lifetime, which will be checked // later, at which point a suitable error will be emitted. + AnonymousLifetimeRib::Elided(node_id, Some(_)) => { + let res = LifetimeRes::Anonymous { binder: node_id, elided: true }; + (true, res) + } + AnonymousLifetimeRib::Elided(node_id, None) => { + self.diagnostic_metadata.current_elision_failures.push(MissingLifetime { + span: elided_lifetime_span, + kind: if segment.has_generic_args { + MissingLifetimeKind::Comma + } else { + MissingLifetimeKind::Brackets + }, + count: expected_lifetimes, + }); + (true, LifetimeRes::Anonymous { binder: node_id, elided: true }) + } AnonymousLifetimeRib::PassThrough(binder) => { - LifetimeRes::Anonymous { binder: *binder, elided: true } + let res = LifetimeRes::Anonymous { binder, elided: true }; + (true, res) } - // FIXME(cjgillot) This resolution is wrong, but this does not matter - // since these cases are erroneous anyway. Lifetime resolution should - // emit a "missing lifetime specifier" diagnostic. - AnonymousLifetimeRib::ReportError | AnonymousLifetimeRib::Item => { - LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true } + AnonymousLifetimeRib::Item | AnonymousLifetimeRib::ReportError => { + self.report_missing_lifetime_specifiers( + vec![MissingLifetime { + span: elided_lifetime_span, + kind: if segment.has_generic_args { + MissingLifetimeKind::Comma + } else { + MissingLifetimeKind::Brackets + }, + count: expected_lifetimes, + }], + None, + ); + (true, LifetimeRes::Error) } - AnonymousLifetimeRib::Static => LifetimeRes::Static, + AnonymousLifetimeRib::Static => (true, LifetimeRes::Static), }; + debug!(?lint, ?res); let node_ids = self.r.next_node_ids(expected_lifetimes); + let ident = Ident::new(kw::UnderscoreLifetime, elided_lifetime_span); self.record_lifetime_res( segment_id, + ident, LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end }, ); for i in 0..expected_lifetimes { let id = node_ids.start.plus(i); - self.record_lifetime_res(id, res); - } - - if !missing { - continue; + self.record_lifetime_res(id, ident, res); } - let elided_lifetime_span = if segment.has_generic_args { - // If there are brackets, but not generic arguments, then use the opening bracket - segment.args_span.with_hi(segment.args_span.lo() + BytePos(1)) - } else { - // If there are no brackets, use the identifier span. - // HACK: we use find_ancestor_inside to properly suggest elided spans in paths - // originating from macros, since the segment's span might be from a macro arg. - segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span) + let missing = match source { + PathSource::Trait(..) | PathSource::TraitItem(..) | PathSource::Type => true, + PathSource::Expr(..) + | PathSource::Pat + | PathSource::Struct + | PathSource::TupleStruct(..) => false, }; - if let LifetimeRes::Error = res { - let sess = self.r.session; - let mut err = rustc_errors::struct_span_err!( - sess, - path_span, - E0726, - "implicit elided lifetime not allowed here" - ); - rustc_errors::add_elided_lifetime_in_path_suggestion( - sess.source_map(), - &mut err, - expected_lifetimes, - path_span, - !segment.has_generic_args, - elided_lifetime_span, - ); - err.note("assuming a `'static` lifetime..."); - err.emit(); - } else { + + if missing && lint { self.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::ELIDED_LIFETIMES_IN_PATHS, segment_id, @@ -1466,13 +1557,175 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } #[tracing::instrument(level = "debug", skip(self))] - fn record_lifetime_res(&mut self, id: NodeId, res: LifetimeRes) { + fn record_lifetime_res(&mut self, id: NodeId, ident: Ident, res: LifetimeRes) { if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { panic!( "lifetime {:?} resolved multiple times ({:?} before, {:?} now)", id, prev_res, res ) } + match res { + LifetimeRes::Param { .. } + | LifetimeRes::Fresh { .. } + | LifetimeRes::Anonymous { .. } + | LifetimeRes::Static => { + if let Some(ref mut candidates) = self.lifetime_elision_candidates { + candidates.push((ident, res)); + } + } + LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {} + } + } + + #[tracing::instrument(level = "debug", skip(self, inputs))] + fn resolve_fn_like_elision( + &mut self, + fn_id: NodeId, + async_node_id: Option, + has_self: bool, + inputs: impl Iterator, &'ast Ty)> + Clone, + output_ty: &'ast FnRetTy, + ) { + // Add each argument to the rib. + let parameter_rib = if async_node_id.is_some() { + AnonymousLifetimeRib::CreateParameter(fn_id) + } else { + AnonymousLifetimeRib::PassThrough(fn_id) + }; + let elision_lifetime = self + .with_anon_lifetime_rib(parameter_rib, |this| this.elision_lifetime(has_self, inputs)); + debug!(?elision_lifetime); + + if let Some(async_node_id) = async_node_id { + // Construct the list of in-scope lifetime parameters for async lowering. + // We include all lifetime parameters, either named or "Fresh". + // The order of those parameters does not matter, as long as it is + // deterministic. + let mut extra_lifetime_params = + self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default(); + for rib in self.lifetime_ribs.iter().rev() { + extra_lifetime_params.extend( + rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)), + ); + if let LifetimeRibKind::Item = rib.kind { + break; + } + } + for rib in self.anonymous_lifetime_ribs.iter().rev() { + match rib { + AnonymousLifetimeRib::Item => break, + AnonymousLifetimeRib::CreateParameter(id) => { + if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&id) { + extra_lifetime_params.extend(earlier_fresh); + } + } + _ => {} + } + } + self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); + } + + let outer_failures = std::mem::take(&mut self.diagnostic_metadata.current_elision_failures); + let output_rib = AnonymousLifetimeRib::Elided( + async_node_id.unwrap_or(fn_id), + elision_lifetime.as_ref().ok().copied(), + ); + self.with_anon_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, &output_ty)); + let elision_failures = std::mem::replace( + &mut self.diagnostic_metadata.current_elision_failures, + outer_failures, + ); + if let Err(failure_info) = elision_lifetime && !elision_failures.is_empty() { + self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); + } + } + + fn elision_lifetime( + &mut self, + has_self: bool, + inputs: impl Iterator, &'ast Ty)>, + ) -> Result, Vec)> { + let outer_candidates = + std::mem::replace(&mut self.lifetime_elision_candidates, Some(Vec::new())); + + let mut elision_lifetime = None; + let mut lifetime_count = 0; + let mut parameter_info = Vec::new(); + + let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; + for (index, (pat, ty)) in inputs.enumerate() { + debug!(?pat, ?ty); + if let Some(pat) = pat { + self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); + } + self.visit_ty(ty); + + if let Some(ref candidates) = self.lifetime_elision_candidates { + let new_count = candidates.len(); + let local_count = new_count - lifetime_count; + if local_count != 0 { + parameter_info.push(ElisionFailureInfo { + index, + ident: if let Some(pat) = pat && let PatKind::Ident(_, ident, _) = pat.kind { + Some(ident) + } else { + None + }, + lifetime_count: local_count, + span: ty.span, + }); + } + lifetime_count = new_count; + } + + // Handle `self` specially. + if index == 0 && has_self { + debug!(?self.lifetime_elision_candidates); + if let TyKind::Rptr(lt, _) = ty.kind { + let lt_id = if let Some(lt) = lt { + lt.id + } else { + let res = self.r.lifetimes_res_map[&ty.id]; + let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() }; + start + }; + elision_lifetime = Some(self.r.lifetimes_res_map[<_id]); + // No need to keep registering candidates. + self.lifetime_elision_candidates = None; + } else { + let candidates = self.lifetime_elision_candidates.as_mut().unwrap(); + if let [(_, candidate)] = &candidates[..] { + // We only have one lifetime appearing in `self`: this is our elision. + elision_lifetime = Some(*candidate); + // No need to keep registering candidates. + self.lifetime_elision_candidates = None; + } else { + // We have multiple lifetimes for `self`, disregard them and use + // another parameter's lifetime. + candidates.clear(); + lifetime_count = 0; + } + } + } + debug!("(resolving function / closure) recorded parameter"); + } + + let all_candidates = + std::mem::replace(&mut self.lifetime_elision_candidates, outer_candidates); + debug!(?all_candidates); + + if let Some(res) = elision_lifetime { + return Ok(res); + } + + // We do not have a `self` candidate, look at the full list. + let all_candidates = all_candidates.unwrap(); + if let [(_, candidate)] = &all_candidates[..] { + Ok(*candidate) + } else { + let all_lifetimes = all_candidates.iter().map(|&(ident, _)| ident).collect(); + Err((all_lifetimes, parameter_info)) + } } /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved @@ -1838,7 +2091,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { GenericParamKind::Lifetime => { let LifetimeRibKind::Generics { parent, .. } = lifetime_kind else { panic!() }; let res = LifetimeRes::Param { param: def_id, binder: parent }; - self.record_lifetime_res(param.id, res); + if let Some(prev_res) = self.r.lifetimes_res_map.insert(param.id, res) { + panic!( + "lifetime {:?} resolved multiple times ({:?} before, {:?} now)", + param, prev_res, res + ) + } function_lifetime_rib.bindings.insert(ident, (param.id, res)); continue; } @@ -2016,50 +2274,67 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ) { debug!("resolve_implementation"); // If applicable, create a rib for the type parameters. - self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, parent: item_id, kind: LifetimeBinderKind::ImplBlock }, |this| { - // Dummy self type for better errors if `Self` is used in the trait path. - this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| { - this.with_anon_lifetime_rib(AnonymousLifetimeRib::CreateParameter(item_id), |this| { - // Resolve the trait reference, if necessary. - this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { - let item_def_id = this.r.local_def_id(item_id); - - // Register the trait definitions from here. - if let Some(trait_id) = trait_id { - this.r.trait_impls.entry(trait_id).or_default().push(item_def_id); - } - - let item_def_id = item_def_id.to_def_id(); - let res = - Res::SelfTy { trait_: trait_id, alias_to: Some((item_def_id, false)) }; - this.with_self_rib(res, |this| { - if let Some(trait_ref) = opt_trait_reference.as_ref() { - // Resolve type arguments in the trait path. - visit::walk_trait_ref(this, trait_ref); - } - // Resolve the self type. - this.visit_ty(self_type); - // Resolve the generic parameters. - this.visit_generics(generics); - - // Resolve the items within the impl. - this.with_anon_lifetime_rib(AnonymousLifetimeRib::PassThrough(item_id), - |this| { - this.with_current_self_type(self_type, |this| { - this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { - debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); - for item in impl_items { - this.resolve_impl_item(&**item); - } + self.with_generic_param_rib( + &generics.params, + ItemRibKind(HasGenericParams::Yes), + LifetimeRibKind::Generics { + span: generics.span, + parent: item_id, + kind: LifetimeBinderKind::ImplBlock, + }, + |this| { + // Dummy self type for better errors if `Self` is used in the trait path. + this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| { + this.with_anon_lifetime_rib( + AnonymousLifetimeRib::CreateParameter(item_id), + |this| { + // Resolve the trait reference, if necessary. + this.with_optional_trait_ref( + opt_trait_reference.as_ref(), + |this, trait_id| { + let item_def_id = this.r.local_def_id(item_id); + + // Register the trait definitions from here. + if let Some(trait_id) = trait_id { + this.r + .trait_impls + .entry(trait_id) + .or_default() + .push(item_def_id); + } + + let item_def_id = item_def_id.to_def_id(); + let res = Res::SelfTy { + trait_: trait_id, + alias_to: Some((item_def_id, false)), + }; + this.with_self_rib(res, |this| { + if let Some(trait_ref) = opt_trait_reference.as_ref() { + // Resolve type arguments in the trait path. + visit::walk_trait_ref(this, trait_ref); + } + // Resolve the self type. + this.visit_ty(self_type); + // Resolve the generic parameters. + this.visit_generics(generics); + + // Resolve the items within the impl. + this.with_current_self_type(self_type, |this| { + this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { + debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); + for item in impl_items { + this.resolve_impl_item(&**item); + } + }); }); }); }, ); - }); - }); + }, + ); }); - }); - }); + }, + ); } fn resolve_impl_item(&mut self, item: &'ast AssocItem) { @@ -2128,18 +2403,20 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { kind: LifetimeBinderKind::Item, }, |this| { - // If this is a trait impl, ensure the type - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - TypeNS, - item.span, - |i, s, c| TypeNotMemberOfTrait(i, s, c), - ); + this.with_anon_lifetime_rib(AnonymousLifetimeRib::Item, |this| { + // If this is a trait impl, ensure the type + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + TypeNS, + item.span, + |i, s, c| TypeNotMemberOfTrait(i, s, c), + ); - visit::walk_assoc_item(this, item, AssocCtxt::Impl) + visit::walk_assoc_item(this, item, AssocCtxt::Impl) + }) }, ); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 894ff0f17f8a1..403ca2af276ef 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1,7 +1,6 @@ use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion}; -use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext}; -use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind}; -use crate::late::{LifetimeBinderKind, LifetimeRibKind}; +use crate::late::{AliasPossibility, ElisionFailureInfo, LateResolutionVisitor, RibKind}; +use crate::late::{LifetimeBinderKind, LifetimeRibKind, MissingLifetime, MissingLifetimeKind}; use crate::path_names_to_string; use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; @@ -27,7 +26,7 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, Span}; use std::iter; use std::ops::Deref; @@ -57,41 +56,6 @@ impl AssocSuggestion { } } -crate enum MissingLifetimeSpot<'tcx> { - Generics(&'tcx hir::Generics<'tcx>), - HigherRanked { span: Span, span_type: ForLifetimeSpanType }, - Static, -} - -crate enum ForLifetimeSpanType { - BoundEmpty, - BoundTail, - TypeEmpty, - TypeTail, -} - -impl ForLifetimeSpanType { - crate fn descr(&self) -> &'static str { - match self { - Self::BoundEmpty | Self::BoundTail => "bound", - Self::TypeEmpty | Self::TypeTail => "type", - } - } - - crate fn suggestion(&self, sugg: &str) -> String { - match self { - Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg), - Self::BoundTail | Self::TypeTail => format!(", {}", sugg), - } - } -} - -impl<'tcx> Into> for &'tcx hir::Generics<'tcx> { - fn into(self) -> MissingLifetimeSpot<'tcx> { - MissingLifetimeSpot::Generics(self) - } -} - fn is_self_type(path: &[Segment], namespace: Namespace) -> bool { namespace == TypeNS && path.len() == 1 && path[0].ident.name == kw::SelfUpper } @@ -1818,18 +1782,35 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_label(lifetime_ref.ident.span, "undeclared lifetime"); err }; - let mut suggest_note = true; + self.suggest_introducing_lifetime( + &mut err, + Some(lifetime_ref.ident.name.as_str()), + |err, _, span, message, suggestion| { + err.span_suggestion(span, message, suggestion, Applicability::MaybeIncorrect); + true + }, + ); + err.emit(); + } + fn suggest_introducing_lifetime( + &self, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + name: Option<&str>, + suggest: impl Fn(&mut DiagnosticBuilder<'_, ErrorGuaranteed>, bool, Span, &str, String) -> bool, + ) { + let mut suggest_note = true; for rib in self.lifetime_ribs.iter().rev() { + let mut should_continue = true; match rib.kind { LifetimeRibKind::Generics { parent: _, span, kind } => { - if !span.can_be_used_for_suggestions() && suggest_note { + if !span.can_be_used_for_suggestions() && suggest_note && let Some(name) = name { suggest_note = false; // Avoid displaying the same help multiple times. err.span_label( span, &format!( "lifetime `{}` is missing in item created through this procedural macro", - lifetime_ref.ident, + name, ), ); continue; @@ -1845,46 +1826,42 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let sugg = format!( "{}<{}>{}", if higher_ranked { "for" } else { "" }, - lifetime_ref.ident, + name.unwrap_or("'a"), if higher_ranked { " " } else { "" }, ); (span, sugg) } else { let span = self.r.session.source_map().span_through_char(span, '<').shrink_to_hi(); - let sugg = format!("{}, ", lifetime_ref.ident); + let sugg = format!("{}, ", name.unwrap_or("'a")); (span, sugg) }; if higher_ranked { - err.span_suggestion( - span, - &format!( - "consider making the {} lifetime-generic with a new `{}` lifetime", - kind.descr(), - lifetime_ref - ), - sugg, - Applicability::MaybeIncorrect, + let message = format!( + "consider making the {} lifetime-generic with a new `{}` lifetime", + kind.descr(), + name.unwrap_or("'a"), ); + should_continue = suggest(err, true, span, &message, sugg); err.note_once( "for more information on higher-ranked polymorphism, visit \ https://doc.rust-lang.org/nomicon/hrtb.html", ); + } else if let Some(name) = name { + let message = format!("consider introducing lifetime `{}` here", name); + should_continue = suggest(err, false, span, &message, sugg); } else { - err.span_suggestion( - span, - &format!("consider introducing lifetime `{}` here", lifetime_ref.ident), - sugg, - Applicability::MaybeIncorrect, - ); + let message = format!("consider introducing a named lifetime parameter"); + should_continue = suggest(err, false, span, &message, sugg); } } LifetimeRibKind::Item => break, _ => {} } + if !should_continue { + break; + } } - - err.emit(); } crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &ast::Lifetime) { @@ -1917,490 +1894,184 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { .emit(); } } -} -impl<'tcx> LifetimeContext<'_, 'tcx> { crate fn report_missing_lifetime_specifiers( &self, - spans: Vec, - count: usize, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - struct_span_err!( - self.tcx.sess, + lifetime_refs: Vec, + function_param_lifetimes: Option<(Vec, Vec)>, + ) -> ErrorGuaranteed { + let num_lifetimes: usize = lifetime_refs.iter().map(|lt| lt.count).sum(); + let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect(); + + let mut err = struct_span_err!( + self.r.session, spans, E0106, "missing lifetime specifier{}", - pluralize!(count) - ) + pluralize!(num_lifetimes) + ); + self.add_missing_lifetime_specifiers_label( + &mut err, + lifetime_refs, + function_param_lifetimes, + ); + err.emit() } - /// Returns whether to add `'static` lifetime to the suggested lifetime list. - crate fn report_elision_failure( - &mut self, - diag: &mut Diagnostic, - params: &[ElisionFailureInfo], - ) -> bool { - let mut m = String::new(); - let len = params.len(); + crate fn add_missing_lifetime_specifiers_label( + &self, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + lifetime_refs: Vec, + function_param_lifetimes: Option<(Vec, Vec)>, + ) { + for < in &lifetime_refs { + err.span_label( + lt.span, + format!( + "expected {} lifetime parameter{}", + if lt.count == 1 { "named".to_string() } else { lt.count.to_string() }, + pluralize!(lt.count), + ), + ); + } - let elided_params: Vec<_> = - params.iter().cloned().filter(|info| info.lifetime_count > 0).collect(); + let mut in_scope_lifetimes: Vec<_> = self + .lifetime_ribs + .iter() + .flat_map(|rib| rib.bindings.keys().copied()) + .filter(|ident| ident.name != kw::UnderscoreLifetime) + .collect(); - let elided_len = elided_params.len(); + if let Some((param_lifetimes, params)) = function_param_lifetimes { + let elided_len = + param_lifetimes.iter().filter(|ident| ident.name == kw::UnderscoreLifetime).count(); + let num_params = params.len(); - for (i, info) in elided_params.into_iter().enumerate() { - let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } = - info; + let mut m = String::new(); - diag.span_label(span, ""); - let help_name = if let Some(ident) = - parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident()) - { - format!("`{}`", ident) - } else { - format!("argument {}", index + 1) - }; + for (i, info) in params.into_iter().enumerate() { + let ElisionFailureInfo { ident, index, lifetime_count, span } = info; + debug_assert_ne!(lifetime_count, 0); + + err.span_label(span, ""); - m.push_str( - &(if n == 1 { - help_name + if i != 0 { + if i + 1 < num_params { + m.push_str(", "); + } else if num_params == 2 { + m.push_str(" or "); + } else { + m.push_str(", or "); + } + } + + let help_name = if let Some(ident) = ident { + format!("`{}`", ident) } else { - format!( - "one of {}'s {} {}lifetimes", - help_name, - n, - if have_bound_regions { "free " } else { "" } - ) - })[..], - ); + format!("argument {}", index + 1) + }; - if elided_len == 2 && i == 0 { - m.push_str(" or "); - } else if i + 2 == elided_len { - m.push_str(", or "); - } else if i != elided_len - 1 { - m.push_str(", "); + if lifetime_count == 1 { + m.push_str(&help_name[..]) + } else { + m.push_str(&format!("one of {}'s {} lifetimes", help_name, lifetime_count)[..]) + } } - } - if len == 0 { - diag.help( - "this function's return type contains a borrowed value, \ + if num_params == 0 { + err.help( + "this function's return type contains a borrowed value, \ but there is no value for it to be borrowed from", - ); - true - } else if elided_len == 0 { - diag.help( - "this function's return type contains a borrowed value with \ + ); + in_scope_lifetimes = vec![Ident::with_dummy_span(kw::StaticLifetime)]; + } else if elided_len == 0 { + err.help( + "this function's return type contains a borrowed value with \ an elided lifetime, but the lifetime cannot be derived from \ the arguments", - ); - true - } else if elided_len == 1 { - diag.help(&format!( - "this function's return type contains a borrowed value, \ + ); + in_scope_lifetimes = vec![Ident::with_dummy_span(kw::StaticLifetime)]; + } else if num_params == 1 { + err.help(&format!( + "this function's return type contains a borrowed value, \ but the signature does not say which {} it is borrowed from", - m - )); - false - } else { - diag.help(&format!( - "this function's return type contains a borrowed value, \ + m + )); + } else { + err.help(&format!( + "this function's return type contains a borrowed value, \ but the signature does not say whether it is borrowed from {}", - m - )); - false - } - } - - crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool { - if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res { - if [ - self.tcx.lang_items().fn_once_trait(), - self.tcx.lang_items().fn_trait(), - self.tcx.lang_items().fn_mut_trait(), - ] - .contains(&Some(did)) - { - let (span, span_type) = match &trait_ref.bound_generic_params { - [] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty), - [.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail), - }; - self.missing_named_lifetime_spots - .push(MissingLifetimeSpot::HigherRanked { span, span_type }); - return true; - } - }; - false - } - - crate fn add_missing_lifetime_specifiers_label( - &self, - err: &mut Diagnostic, - mut spans_with_counts: Vec<(Span, usize)>, - lifetime_names: &FxHashSet, - lifetime_spans: Vec, - params: &[ElisionFailureInfo], - ) { - let snippets: Vec> = spans_with_counts - .iter() - .map(|(span, _)| self.tcx.sess.source_map().span_to_snippet(*span).ok()) - .collect(); - - // Empty generics are marked with a span of "<", but since from now on - // that information is in the snippets it can be removed from the spans. - for ((span, _), snippet) in spans_with_counts.iter_mut().zip(&snippets) { - if snippet.as_deref() == Some("<") { - *span = span.shrink_to_hi(); + m + )); } } - for &(span, count) in &spans_with_counts { - err.span_label( - span, - format!( - "expected {} lifetime parameter{}", - if count == 1 { "named".to_string() } else { count.to_string() }, - pluralize!(count), - ), - ); - } - - let suggest_existing = - |err: &mut Diagnostic, - name: &str, - formatters: Vec String>>>| { - if let Some(MissingLifetimeSpot::HigherRanked { span: for_span, span_type }) = - self.missing_named_lifetime_spots.iter().rev().next() - { - // When we have `struct S<'a>(&'a dyn Fn(&X) -> &X);` we want to not only suggest - // using `'a`, but also introduce the concept of HRLTs by suggesting - // `struct S<'a>(&'a dyn for<'b> Fn(&X) -> &'b X);`. (#72404) - let mut introduce_suggestion = vec![]; - - let a_to_z_repeat_n = |n| { - (b'a'..=b'z').map(move |c| { - let mut s = '\''.to_string(); - s.extend(std::iter::repeat(char::from(c)).take(n)); - s - }) - }; + let existing_name = match &in_scope_lifetimes[..] { + [] => Symbol::intern("'a"), + [existing] => existing.name, + _ => Symbol::intern("'lifetime"), + }; - // If all single char lifetime names are present, we wrap around and double the chars. - let lt_name = (1..) - .flat_map(a_to_z_repeat_n) - .find(|lt| !lifetime_names.contains(&Symbol::intern(<))) - .unwrap(); - let msg = format!( - "consider making the {} lifetime-generic with a new `{}` lifetime", - span_type.descr(), - lt_name, - ); - err.note( - "for more information on higher-ranked polymorphism, visit \ - https://doc.rust-lang.org/nomicon/hrtb.html", - ); - let for_sugg = span_type.suggestion(<_name); - for param in params { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) - { - if snippet.starts_with('&') && !snippet.starts_with("&'") { - introduce_suggestion - .push((param.span, format!("&{} {}", lt_name, &snippet[1..]))); - } else if let Some(stripped) = snippet.strip_prefix("&'_ ") { - introduce_suggestion - .push((param.span, format!("&{} {}", lt_name, stripped))); - } - } - } - introduce_suggestion.push((*for_span, for_sugg)); - for ((span, _), formatter) in spans_with_counts.iter().zip(formatters.iter()) { - if let Some(formatter) = formatter { - introduce_suggestion.push((*span, formatter(<_name))); - } - } - err.multipart_suggestion_verbose( - &msg, - introduce_suggestion, - Applicability::MaybeIncorrect, - ); + let mut spans_suggs: Vec<_> = Vec::new(); + for < in &lifetime_refs { + let (span, sugg) = match lt.kind { + MissingLifetimeKind::Underscore => { + debug_assert_eq!(lt.count, 1); + (lt.span, existing_name.to_string()) } - - let spans_suggs: Vec<_> = formatters - .into_iter() - .zip(spans_with_counts.iter()) - .filter_map(|(formatter, (span, _))| { - if let Some(formatter) = formatter { - Some((*span, formatter(name))) - } else { - None - } - }) - .collect(); - if spans_suggs.is_empty() { - // If all the spans come from macros, we cannot extract snippets and then - // `formatters` only contains None and `spans_suggs` is empty. - return; + MissingLifetimeKind::Ampersand => { + debug_assert_eq!(lt.count, 1); + (lt.span.shrink_to_hi(), format!("{} ", existing_name)) + } + MissingLifetimeKind::Comma => { + let sugg: String = std::iter::repeat([existing_name.as_str(), ", "]) + .take(lt.count) + .flatten() + .collect(); + (lt.span.shrink_to_hi(), sugg) + } + MissingLifetimeKind::Brackets => { + let sugg: String = std::iter::once("<") + .chain( + std::iter::repeat(existing_name.as_str()) + .take(lt.count) + .intersperse(", "), + ) + .chain([">"]) + .collect(); + (lt.span.shrink_to_hi(), sugg) } - err.multipart_suggestion_verbose( - &format!( - "consider using the `{}` lifetime", - lifetime_names.iter().next().unwrap() - ), - spans_suggs, - Applicability::MaybeIncorrect, - ); }; - let suggest_new = |err: &mut Diagnostic, suggs: Vec>| { - for missing in self.missing_named_lifetime_spots.iter().rev() { - let mut introduce_suggestion = vec![]; - let msg; - let should_break; - introduce_suggestion.push(match missing { - MissingLifetimeSpot::Generics(generics) => { - if generics.span == DUMMY_SP { - // Account for malformed generics in the HIR. This shouldn't happen, - // but if we make a mistake elsewhere, mainly by keeping something in - // `missing_named_lifetime_spots` that we shouldn't, like associated - // `const`s or making a mistake in the AST lowering we would provide - // nonsensical suggestions. Guard against that by skipping these. - // (#74264) - continue; - } - msg = "consider introducing a named lifetime parameter".to_string(); - should_break = true; - if let Some(param) = generics.params.iter().find(|p| { - !matches!( - p.kind, - hir::GenericParamKind::Type { synthetic: true, .. } - | hir::GenericParamKind::Lifetime { - kind: hir::LifetimeParamKind::Elided - } - ) - }) { - (param.span.shrink_to_lo(), "'a, ".to_string()) - } else { - (generics.span, "<'a>".to_string()) - } - } - MissingLifetimeSpot::HigherRanked { span, span_type } => { - msg = format!( - "consider making the {} lifetime-generic with a new `'a` lifetime", - span_type.descr(), - ); - should_break = false; - err.note( - "for more information on higher-ranked polymorphism, visit \ - https://doc.rust-lang.org/nomicon/hrtb.html", - ); - (*span, span_type.suggestion("'a")) - } - MissingLifetimeSpot::Static => { - let mut spans_suggs = Vec::new(); - for ((span, count), snippet) in - spans_with_counts.iter().copied().zip(snippets.iter()) - { - let (span, sugg) = match snippet.as_deref() { - Some("&") => (span.shrink_to_hi(), "'static ".to_owned()), - Some("'_") => (span, "'static".to_owned()), - Some(snippet) if !snippet.ends_with('>') => { - if snippet == "" { - ( - span, - std::iter::repeat("'static") - .take(count) - .collect::>() - .join(", "), - ) - } else if snippet == "<" || snippet == "(" { - ( - span.shrink_to_hi(), - std::iter::repeat("'static") - .take(count) - .collect::>() - .join(", "), - ) - } else { - ( - span.shrink_to_hi(), - format!( - "<{}>", - std::iter::repeat("'static") - .take(count) - .collect::>() - .join(", "), - ), - ) - } - } - _ => continue, - }; - spans_suggs.push((span, sugg.to_string())); - } + spans_suggs.push((span, sugg)); + } + match in_scope_lifetimes.len() { + 0 => { + self.suggest_introducing_lifetime( + err, + None, + |err, higher_ranked, span, message, intro_sugg| { err.multipart_suggestion_verbose( - "consider using the `'static` lifetime", - spans_suggs, + message, + std::iter::once((span, intro_sugg)) + .chain(spans_suggs.clone()) + .collect(), Applicability::MaybeIncorrect, ); - continue; - } - }); - - struct Lifetime(Span, String); - impl Lifetime { - fn is_unnamed(&self) -> bool { - self.1.starts_with('&') && !self.1.starts_with("&'") - } - fn is_underscore(&self) -> bool { - self.1.starts_with("&'_ ") - } - fn is_named(&self) -> bool { - self.1.starts_with("&'") - } - fn suggestion(&self, sugg: String) -> Option<(Span, String)> { - Some( - match ( - self.is_unnamed(), - self.is_underscore(), - self.is_named(), - sugg.starts_with('&'), - ) { - (true, _, _, false) => (self.span_unnamed_borrow(), sugg), - (true, _, _, true) => { - (self.span_unnamed_borrow(), sugg[1..].to_string()) - } - (_, true, _, false) => { - (self.span_underscore_borrow(), sugg.trim().to_string()) - } - (_, true, _, true) => { - (self.span_underscore_borrow(), sugg[1..].trim().to_string()) - } - (_, _, true, false) => { - (self.span_named_borrow(), sugg.trim().to_string()) - } - (_, _, true, true) => { - (self.span_named_borrow(), sugg[1..].trim().to_string()) - } - _ => return None, - }, - ) - } - fn span_unnamed_borrow(&self) -> Span { - let lo = self.0.lo() + BytePos(1); - self.0.with_lo(lo).with_hi(lo) - } - fn span_named_borrow(&self) -> Span { - let lo = self.0.lo() + BytePos(1); - self.0.with_lo(lo) - } - fn span_underscore_borrow(&self) -> Span { - let lo = self.0.lo() + BytePos(1); - let hi = lo + BytePos(2); - self.0.with_lo(lo).with_hi(hi) - } - } - - for param in params { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) { - if let Some((span, sugg)) = - Lifetime(param.span, snippet).suggestion("'a ".to_string()) - { - introduce_suggestion.push((span, sugg)); - } - } - } - for (span, sugg) in spans_with_counts.iter().copied().zip(suggs.iter()).filter_map( - |((span, _), sugg)| match &sugg { - Some(sugg) => Some((span, sugg.to_string())), - _ => None, + higher_ranked }, - ) { - let (span, sugg) = self - .tcx - .sess - .source_map() - .span_to_snippet(span) - .ok() - .and_then(|snippet| Lifetime(span, snippet).suggestion(sugg.clone())) - .unwrap_or((span, sugg)); - introduce_suggestion.push((span, sugg.to_string())); - } + ); + } + 1 => { err.multipart_suggestion_verbose( - &msg, - introduce_suggestion, + &format!("consider using the `{}` lifetime", existing_name), + spans_suggs, Applicability::MaybeIncorrect, ); - if should_break { - break; - } - } - }; - - let lifetime_names: Vec<_> = lifetime_names.iter().collect(); - match &lifetime_names[..] { - [name] => { - let mut suggs: Vec String>>> = Vec::new(); - for (snippet, (_, count)) in snippets.iter().zip(spans_with_counts.iter().copied()) - { - suggs.push(match snippet.as_deref() { - Some("&") => Some(Box::new(|name| format!("&{} ", name))), - Some("'_") => Some(Box::new(|n| n.to_string())), - Some("") => Some(Box::new(move |n| format!("{}, ", n).repeat(count))), - Some("<") => Some(Box::new(move |n| { - std::iter::repeat(n).take(count).collect::>().join(", ") - })), - Some(snippet) if !snippet.ends_with('>') => Some(Box::new(move |name| { - format!( - "{}<{}>", - snippet, - std::iter::repeat(name.to_string()) - .take(count) - .collect::>() - .join(", ") - ) - })), - _ => None, - }); - } - suggest_existing(err, name.as_str(), suggs); - } - [] => { - let mut suggs = Vec::new(); - for (snippet, (_, count)) in - snippets.iter().cloned().zip(spans_with_counts.iter().copied()) - { - suggs.push(match snippet.as_deref() { - Some("&") => Some("&'a ".to_string()), - Some("'_") => Some("'a".to_string()), - Some("") => { - Some(std::iter::repeat("'a, ").take(count).collect::>().join("")) - } - Some("<") => { - Some(std::iter::repeat("'a").take(count).collect::>().join(", ")) - } - Some(snippet) => Some(format!( - "{}<{}>", - snippet, - std::iter::repeat("'a").take(count).collect::>().join(", "), - )), - None => None, - }); - } - suggest_new(err, suggs); } - lts if lts.len() > 1 => { + _ => { + let lifetime_spans: Vec<_> = in_scope_lifetimes.iter().map(|i| i.span).collect(); err.span_note(lifetime_spans, "these named lifetimes are available to use"); - let mut spans_suggs: Vec<_> = Vec::new(); - for ((span, _), snippet) in spans_with_counts.iter().copied().zip(snippets.iter()) { - match snippet.as_deref() { - Some("") => spans_suggs.push((span, "'lifetime, ".to_string())), - Some("&") => spans_suggs - .push((span.with_lo(span.lo() + BytePos(1)), "'lifetime ".to_string())), - _ => {} - } - } - if spans_suggs.len() > 0 { // This happens when we have `Foo` where we point at the space before `T`, // but this can be confusing so we give a suggestion with placeholders. @@ -2411,7 +2082,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { ); } } - _ => unreachable!(), } } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 35a40a0a32131..51e1b85489595 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -6,7 +6,6 @@ //! used between functions, and they operate in a purely top-down //! way. Therefore, we break lifetime name resolution into a separate pass. -use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot}; use rustc_ast::walk_list; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{struct_span_err, Applicability, Diagnostic}; @@ -176,10 +175,6 @@ crate struct LifetimeContext<'a, 'tcx> { xcrate_object_lifetime_defaults: DefIdMap>, lifetime_uses: &'a mut DefIdMap>, - - /// When encountering an undefined named lifetime, we will suggest introducing it in these - /// places. - crate missing_named_lifetime_spots: Vec>, } #[derive(Debug)] @@ -345,23 +340,12 @@ enum Elide { /// Always use this one lifetime. Exact(Region), /// Less or more than one lifetime were found, error on unspecified. - Error(Vec), + Error, /// Forbid lifetime elision inside of a larger scope where it would be /// permitted. For example, in let position impl trait. Forbid, } -#[derive(Clone, Debug)] -crate struct ElisionFailureInfo { - /// Where we can find the argument pattern. - crate parent: Option, - /// The index of the argument in the original definition. - crate index: usize, - crate lifetime_count: usize, - crate have_bound_regions: bool, - crate span: Span, -} - type ScopeRef<'a> = &'a Scope<'a>; const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root; @@ -454,7 +438,6 @@ fn do_resolve( labels_in_fn: vec![], xcrate_object_lifetime_defaults: Default::default(), lifetime_uses: &mut Default::default(), - missing_named_lifetime_spots: vec![], }; visitor.visit_item(item); @@ -724,11 +707,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } match item.kind { hir::ItemKind::Fn(ref sig, ref generics, _) => { - self.missing_named_lifetime_spots.push(generics.into()); self.visit_early_late(None, item.hir_id(), &sig.decl, generics, |this| { intravisit::walk_item(this, item); }); - self.missing_named_lifetime_spots.pop(); } hir::ItemKind::ExternCrate(_) @@ -798,8 +779,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { | hir::ItemKind::Trait(_, _, ref generics, ..) | hir::ItemKind::TraitAlias(ref generics, ..) | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => { - self.missing_named_lifetime_spots.push(generics.into()); - // Impls permit `'_` to be used and it is equivalent to "some fresh lifetime name". // This is not true for other kinds of items. let track_lifetime_uses = matches!(item.kind, hir::ItemKind::Impl { .. }); @@ -841,7 +820,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { intravisit::walk_item(this, item); }); }); - self.missing_named_lifetime_spots.pop(); } } } @@ -867,18 +845,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { match ty.kind { hir::TyKind::BareFn(ref c) => { let next_early_index = self.next_early_index(); - let lifetime_span: Option = - c.generic_params.iter().rev().find_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param.span), - _ => None, - }); - let (span, span_type) = if let Some(span) = lifetime_span { - (span.shrink_to_hi(), ForLifetimeSpanType::TypeTail) - } else { - (ty.span.shrink_to_lo(), ForLifetimeSpanType::TypeEmpty) - }; - self.missing_named_lifetime_spots - .push(MissingLifetimeSpot::HigherRanked { span, span_type }); let (lifetimes, binders): (FxIndexMap, Vec<_>) = c .generic_params .iter() @@ -907,7 +873,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.check_lifetime_params(old_scope, &c.generic_params); intravisit::walk_ty(this, ty); }); - self.missing_named_lifetime_spots.pop(); } hir::TyKind::TraitObject(bounds, ref lifetime, _) => { debug!(?bounds, ?lifetime, "TraitObject"); @@ -1122,7 +1087,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { use self::hir::TraitItemKind::*; match trait_item.kind { Fn(ref sig, _) => { - self.missing_named_lifetime_spots.push((&trait_item.generics).into()); let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(trait_item.hir_id())), @@ -1131,10 +1095,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { &trait_item.generics, |this| intravisit::walk_trait_item(this, trait_item), ); - self.missing_named_lifetime_spots.pop(); } Type(bounds, ref ty) => { - self.missing_named_lifetime_spots.push((&trait_item.generics).into()); let generics = &trait_item.generics; let mut index = self.next_early_index(); debug!("visit_ty: index = {}", index); @@ -1176,14 +1138,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }) }); - self.missing_named_lifetime_spots.pop(); } Const(_, _) => { // Only methods and types support generics. assert!(trait_item.generics.params.is_empty()); - self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static); intravisit::walk_trait_item(self, trait_item); - self.missing_named_lifetime_spots.pop(); } } } @@ -1192,7 +1151,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { use self::hir::ImplItemKind::*; match impl_item.kind { Fn(ref sig, _) => { - self.missing_named_lifetime_spots.push((&impl_item.generics).into()); let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(impl_item.hir_id())), @@ -1201,11 +1159,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { &impl_item.generics, |this| intravisit::walk_impl_item(this, impl_item), ); - self.missing_named_lifetime_spots.pop(); } TyAlias(ref ty) => { let generics = &impl_item.generics; - self.missing_named_lifetime_spots.push(generics.into()); let mut index = self.next_early_index(); let mut non_lifetime_count = 0; debug!("visit_ty: index = {}", index); @@ -1241,14 +1197,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.visit_ty(ty); }) }); - self.missing_named_lifetime_spots.pop(); } Const(_, _) => { // Only methods and types support generics. assert!(impl_item.generics.params.is_empty()); - self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static); intravisit::walk_impl_item(self, impl_item); - self.missing_named_lifetime_spots.pop(); } } } @@ -1443,8 +1396,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { ) { debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref); - let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref); - let next_early_index = self.next_early_index(); let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); @@ -1486,10 +1437,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); this.visit_trait_ref(&trait_ref.trait_ref); }); - - if should_pop_missing_lt { - self.missing_named_lifetime_spots.pop(); - } } } @@ -1783,7 +1730,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let LifetimeContext { tcx, map, lifetime_uses, .. } = self; let labels_in_fn = take(&mut self.labels_in_fn); let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults); - let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots); let mut this = LifetimeContext { tcx: *tcx, map, @@ -1792,7 +1738,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { labels_in_fn, xcrate_object_lifetime_defaults, lifetime_uses, - missing_named_lifetime_spots, }; let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); { @@ -1804,7 +1749,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } self.labels_in_fn = this.labels_in_fn; self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults; - self.missing_named_lifetime_spots = this.missing_named_lifetime_spots; } /// helper method to determine the span to remove when suggesting the @@ -2653,24 +2597,20 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let mut assoc_item_kind = None; let mut impl_self = None; let parent = self.tcx.hir().get_parent_node(output.hir_id); - let body = match self.tcx.hir().get(parent) { + match self.tcx.hir().get(parent) { // `fn` definitions and methods. - Node::Item(&hir::Item { kind: hir::ItemKind::Fn(.., body), .. }) => Some(body), + Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. }) => {} - Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => { + Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) => { if let hir::ItemKind::Trait(.., ref trait_items) = self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind { assoc_item_kind = trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind); } - match *m { - hir::TraitFn::Required(_) => None, - hir::TraitFn::Provided(body) => Some(body), - } } - Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => { + Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, _), .. }) => { if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) = self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind { @@ -2678,11 +2618,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { assoc_item_kind = items.iter().find(|ii| ii.id.hir_id() == parent).map(|ii| ii.kind); } - Some(body) } // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds). - Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => None, + Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => {} // Everything else (only closures?) doesn't // actually enjoy elision in return types. _ => { @@ -2768,42 +2707,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // have that lifetime. let mut possible_implied_output_region = None; let mut lifetime_count = 0; - let arg_lifetimes = inputs - .iter() - .enumerate() - .skip(has_self as usize) - .map(|(i, input)| { - let mut gather = GatherLifetimes { - map: self.map, - outer_index: ty::INNERMOST, - have_bound_regions: false, - lifetimes: Default::default(), - }; - gather.visit_ty(input); - - lifetime_count += gather.lifetimes.len(); + for input in inputs.iter().skip(has_self as usize) { + let mut gather = GatherLifetimes { + map: self.map, + outer_index: ty::INNERMOST, + have_bound_regions: false, + lifetimes: Default::default(), + }; + gather.visit_ty(input); - if lifetime_count == 1 && gather.lifetimes.len() == 1 { - // there's a chance that the unique lifetime of this - // iteration will be the appropriate lifetime for output - // parameters, so lets store it. - possible_implied_output_region = gather.lifetimes.iter().cloned().next(); - } + lifetime_count += gather.lifetimes.len(); - ElisionFailureInfo { - parent: body, - index: i, - lifetime_count: gather.lifetimes.len(), - have_bound_regions: gather.have_bound_regions, - span: input.span, - } - }) - .collect(); + if lifetime_count == 1 && gather.lifetimes.len() == 1 { + // there's a chance that the unique lifetime of this + // iteration will be the appropriate lifetime for output + // parameters, so lets store it. + possible_implied_output_region = gather.lifetimes.iter().cloned().next(); + } + } let elide = if lifetime_count == 1 { Elide::Exact(possible_implied_output_region.unwrap()) } else { - Elide::Error(arg_lifetimes) + Elide::Error }; debug!(?elide); @@ -2935,23 +2861,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let mut late_depth = 0; let mut scope = self.scope; - let mut lifetime_names = FxHashSet::default(); - let mut lifetime_spans = vec![]; - let error = loop { + loop { match *scope { // Do not assign any resolution, it will be inferred. Scope::Body { .. } => return, - Scope::Root => break None, + Scope::Root => break, - Scope::Binder { s, ref lifetimes, scope_type, .. } => { - // collect named lifetimes for suggestions - for name in lifetimes.keys() { - if let hir::ParamName::Plain(name) = name { - lifetime_names.insert(name.name); - lifetime_spans.push(name.span); - } - } + Scope::Binder { s, scope_type, .. } => { match scope_type { BinderScopeType::Normal => late_depth += 1, BinderScopeType::Concatenating => {} @@ -2980,32 +2897,21 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { return; } - Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => { + Scope::Elision { elide: Elide::Error, ref s, .. } => { let mut scope = s; loop { - match scope { - Scope::Binder { ref lifetimes, s, .. } => { - // Collect named lifetimes for suggestions. - for name in lifetimes.keys() { - if let hir::ParamName::Plain(name) = name { - lifetime_names.insert(name.name); - lifetime_spans.push(name.span); - } - } - scope = s; - } - Scope::ObjectLifetimeDefault { ref s, .. } + scope = match scope { + Scope::Binder { ref s, .. } + | Scope::ObjectLifetimeDefault { ref s, .. } | Scope::Elision { ref s, .. } - | Scope::TraitRefBoundary { ref s, .. } => { - scope = s; - } + | Scope::TraitRefBoundary { ref s, .. } => s, _ => break, } } - break Some(&e[..]); + break; } - Scope::Elision { elide: Elide::Forbid, .. } => break None, + Scope::Elision { elide: Elide::Forbid, .. } => break, Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } @@ -3013,7 +2919,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { scope = s; } } - }; + } // If we specifically need the `scope_for_path` map, then we're in the // diagnostic pass and we don't want to emit more errors. @@ -3025,32 +2931,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { return; } - let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect(); - spans.sort(); - let mut spans_dedup = spans.clone(); - spans_dedup.dedup(); - let spans_with_counts: Vec<_> = spans_dedup - .into_iter() - .map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count())) - .collect(); - - let mut err = self.report_missing_lifetime_specifiers(spans.clone(), lifetime_refs.len()); - - if let Some(params) = error { - // If there's no lifetime available, suggest `'static`. - if self.report_elision_failure(&mut err, params) && lifetime_names.is_empty() { - lifetime_names.insert(kw::StaticLifetime); - } + for lt in lifetime_refs { + self.tcx.sess.delay_span_bug(lt.span, "Missing lifetime specifier"); } - - self.add_missing_lifetime_specifiers_label( - &mut err, - spans_with_counts, - &lifetime_names, - lifetime_spans, - error.unwrap_or(&[]), - ); - err.emit(); } fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { @@ -3245,7 +3128,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // necessarily replace a single-use lifetime with // `'_`. Scope::Elision { - elide: Elide::Exact(_) | Elide::Error(_) | Elide::Forbid, .. + elide: Elide::Exact(_) | Elide::Error | Elide::Forbid, .. } => break false, Scope::ObjectLifetimeDefault { s, .. } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 64e228a88d97e..4dc07314f452b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -12,6 +12,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(if_let_guard)] +#![feature(iter_intersperse)] #![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] From 4e5541473b475cca88666297b41b1c45dbaaf61f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 18 Apr 2022 14:44:19 +0200 Subject: [PATCH 09/11] Bless tests. --- .../ui/abi/numbers-arithmetic/i128-ffi.rs | 2 +- ...nd-lifetime-in-binding-only.elision.stderr | 7 +- ...und-lifetime-in-return-only.elision.stderr | 7 +- .../ui/async-await/issues/issue-63388-2.rs | 1 + .../async-await/issues/issue-63388-2.stderr | 34 +- src/test/ui/c-variadic/variadic-ffi-6.stderr | 4 +- src/test/ui/error-codes/E0106.stderr | 22 +- src/test/ui/error-codes/E0637.rs | 2 + src/test/ui/error-codes/E0637.stderr | 46 +- src/test/ui/foreign-fn-return-lifetime.stderr | 2 +- .../gat-trait-path-generic-type-arg.rs | 1 + .../gat-trait-path-generic-type-arg.stderr | 15 +- .../generic-associated-types/issue-70304.rs | 4 +- .../issue-70304.stderr | 29 +- .../generic-associated-types/issue-95305.rs | 8 +- .../issue-95305.stderr | 24 +- ...incorrect-explicit-lifetime-name-needed.rs | 2 + ...rrect-explicit-lifetime-name-needed.stderr | 54 ++- src/test/ui/generics/wrong-number-of-args.rs | 9 + .../ui/generics/wrong-number-of-args.stderr | 429 ++++++++++-------- src/test/ui/issues/issue-13497.stderr | 2 +- src/test/ui/issues/issue-19707.stderr | 17 +- src/test/ui/issues/issue-30255.stderr | 12 +- src/test/ui/lifetimes/issue-26638.rs | 3 + src/test/ui/lifetimes/issue-26638.stderr | 48 +- ...urn-type-requires-explicit-lifetime.stderr | 26 +- .../ex1b-return-no-names-if-else.rs | 7 +- .../ex1b-return-no-names-if-else.stderr | 35 +- .../missing-lifetime-in-alias.stderr | 6 +- .../issue-74918-missing-lifetime.rs | 1 + .../issue-74918-missing-lifetime.stderr | 22 +- .../issue-69401-trait-fn-no-body-ty-local.rs | 2 +- src/test/ui/rfc1623-2.rs | 1 + src/test/ui/rfc1623-2.stderr | 23 +- .../fn-missing-lifetime-in-item.stderr | 9 +- .../impl-trait-missing-lifetime.rs | 2 +- .../impl-trait-missing-lifetime.stderr | 11 +- src/test/ui/suggestions/issue-84592.stderr | 4 +- src/test/ui/suggestions/issue-86667.rs | 2 + src/test/ui/suggestions/issue-86667.stderr | 39 +- ...-lifetimes-in-signature-before-const.fixed | 2 +- ...lifetimes-in-signature-before-const.stderr | 4 +- ...issing-lifetime-in-assoc-const-type.stderr | 16 - .../suggestions/missing-lifetime-specifier.rs | 16 +- .../missing-lifetime-specifier.stderr | 158 +++---- .../ui/suggestions/missing-lt-for-hrtb.rs | 8 +- .../ui/suggestions/missing-lt-for-hrtb.stderr | 94 ++-- .../ui/suggestions/return-elided-lifetime.rs | 15 +- .../suggestions/return-elided-lifetime.stderr | 169 +++---- .../ui/suggestions/return-without-lifetime.rs | 1 + .../return-without-lifetime.stderr | 23 +- ...oxed-closure-sugar-lifetime-elision.stderr | 5 + .../dyn-trait-underscore-in-struct.rs | 3 +- .../dyn-trait-underscore-in-struct.stderr | 11 +- .../in-fn-return-illegal.stderr | 4 +- .../underscore-lifetime-binders.rs | 1 + .../underscore-lifetime-binders.stderr | 49 +- 57 files changed, 839 insertions(+), 714 deletions(-) diff --git a/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs b/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs index 19edf9779f35e..b119e46d7cdba 100644 --- a/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs +++ b/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs @@ -12,7 +12,7 @@ extern "C" { fn identity(f: u128) -> u128; fn square(f: i128) -> i128; - fn sub(f: i128, f: i128) -> i128; + fn sub(f: i128, g: i128) -> i128; } fn main() { diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr index e8e07997c721d..4de4afb6e9246 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -5,15 +5,10 @@ LL | fn elision &i32>() { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html -help: consider making the bound lifetime-generic with a new `'a` lifetime - | -LL | fn elision Fn() -> &'a i32>() { - | +++++++ ~~~ help: consider using the `'static` lifetime | LL | fn elision &'static i32>() { - | ~~~~~~~~ + | +++++++ error: aborting due to previous error diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr index c75e732b7ca4c..7753d186504f8 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -5,15 +5,10 @@ LL | fn elision(_: fn() -> &i32) { | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html -help: consider making the type lifetime-generic with a new `'a` lifetime - | -LL | fn elision(_: for<'a> fn() -> &'a i32) { - | +++++++ ~~~ help: consider using the `'static` lifetime | LL | fn elision(_: fn() -> &'static i32) { - | ~~~~~~~~ + | +++++++ error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-63388-2.rs b/src/test/ui/async-await/issues/issue-63388-2.rs index 458bc9faeaf27..6f49ba96b8d68 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.rs +++ b/src/test/ui/async-await/issues/issue-63388-2.rs @@ -9,6 +9,7 @@ trait Foo {} impl Xyz { async fn do_sth<'a>( foo: &dyn Foo, bar: &'a dyn Foo + //~^ ERROR `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'static` ) -> &dyn Foo //~ ERROR missing lifetime specifier { foo diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr index 24fd3845b4e04..50443213977dc 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -1,8 +1,9 @@ error[E0106]: missing lifetime specifier - --> $DIR/issue-63388-2.rs:12:10 + --> $DIR/issue-63388-2.rs:13:10 | LL | foo: &dyn Foo, bar: &'a dyn Foo | -------- ----------- +LL | LL | ) -> &dyn Foo | ^ expected named lifetime parameter | @@ -10,8 +11,33 @@ LL | ) -> &dyn Foo help: consider using the `'a` lifetime | LL | ) -> &'a dyn Foo - | ~~~ + | ++ -error: aborting due to previous error +error[E0759]: `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/issue-63388-2.rs:11:9 + | +LL | foo: &dyn Foo, bar: &'a dyn Foo + | ^^^ -------- this data with an anonymous lifetime `'_`... + | | + | ...is used here... +... +LL | foo + | --- ...and is required to live as long as `'static` here + | +note: `'static` lifetime requirement introduced by the return type + --> $DIR/issue-63388-2.rs:13:10 + | +LL | ) -> &dyn Foo + | ^^^^^^^^ requirement introduced by this return type +LL | { +LL | foo + | --- because of this returned expression +help: to declare that the trait object captures data from argument `foo`, you can add an explicit `'_` lifetime bound + | +LL | ) -> &dyn Foo + '_ + | ++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0759. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/c-variadic/variadic-ffi-6.stderr b/src/test/ui/c-variadic/variadic-ffi-6.stderr index bb15cc000a46b..4c7792d965019 100644 --- a/src/test/ui/c-variadic/variadic-ffi-6.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-6.stderr @@ -4,11 +4,11 @@ error[E0106]: missing lifetime specifier LL | ) -> &usize { | ^ expected named lifetime parameter | - = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | LL | ) -> &'static usize { - | ~~~~~~~~ + | +++++++ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr index fbd77d9670091..d11a24f776855 100644 --- a/src/test/ui/error-codes/E0106.stderr +++ b/src/test/ui/error-codes/E0106.stderr @@ -23,6 +23,17 @@ LL | A(u8), LL ~ B(&'a bool), | +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:10:14 + | +LL | type MyStr = &str; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type MyStr<'a> = &'a str; + | ++++ ++ + error[E0106]: missing lifetime specifier --> $DIR/E0106.rs:17:10 | @@ -50,17 +61,6 @@ LL | LL ~ buzz: Buzz<'a, 'a>, | -error[E0106]: missing lifetime specifier - --> $DIR/E0106.rs:10:14 - | -LL | type MyStr = &str; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type MyStr<'a> = &'a str; - | ++++ ++ - error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/error-codes/E0637.rs b/src/test/ui/error-codes/E0637.rs index 382ce3ed01f34..48b2f5978892a 100644 --- a/src/test/ui/error-codes/E0637.rs +++ b/src/test/ui/error-codes/E0637.rs @@ -3,8 +3,10 @@ fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { //~| ERROR: missing lifetime specifier if str1.len() > str2.len() { str1 + //~^ ERROR: [E0312] } else { str2 + //~^ ERROR: [E0312] } } diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr index 87aaba65a73ad..ede5110097492 100644 --- a/src/test/ui/error-codes/E0637.stderr +++ b/src/test/ui/error-codes/E0637.stderr @@ -4,12 +4,6 @@ error[E0637]: `'_` cannot be used here LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { | ^^ `'_` is a reserved lifetime name -error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/E0637.rs:13:13 - | -LL | T: Into<&u32>, - | ^ explicit lifetime name needed here - error[E0106]: missing lifetime specifier --> $DIR/E0637.rs:1:62 | @@ -19,10 +13,42 @@ LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `str1` or `str2` help: consider introducing a named lifetime parameter | -LL | fn underscore_lifetime<'a, '_>(str1: &'a str, str2: &'a str) -> &'a str { - | +++ ~~ ~~ ~~ +LL | fn underscore_lifetime<'a, '_>(str1: &'_ str, str2: &'_ str) -> &'a str { + | +++ ~~ + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/E0637.rs:15:13 + | +LL | T: Into<&u32>, + | ^ explicit lifetime name needed here + +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/E0637.rs:5:9 + | +LL | str1 + | ^^^^ + | + = note: ...the reference is valid for the static lifetime... +note: ...but the borrowed content is only valid for the anonymous lifetime defined here + --> $DIR/E0637.rs:1:34 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | ^^^^^^^ + +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/E0637.rs:8:9 + | +LL | str2 + | ^^^^ + | + = note: ...the reference is valid for the static lifetime... +note: ...but the borrowed content is only valid for the anonymous lifetime defined here + --> $DIR/E0637.rs:1:49 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | ^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0106, E0637. +Some errors have detailed explanations: E0106, E0312, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr index b174766cd3d0c..df1a23a19edd5 100644 --- a/src/test/ui/foreign-fn-return-lifetime.stderr +++ b/src/test/ui/foreign-fn-return-lifetime.stderr @@ -8,7 +8,7 @@ LL | pub fn f() -> &u8; help: consider using the `'static` lifetime | LL | pub fn f() -> &'static u8; - | ~~~~~~~~ + | +++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs index 246659a268ac9..11a4f57db28cf 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs @@ -7,6 +7,7 @@ trait Foo { } impl Foo for T { + //~^ ERROR: the type parameter `T1` is not constrained type F = &[u8]; //~^ ERROR: the name `T1` is already used for //~| ERROR: missing lifetime specifier diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr index e82cbf7e8e5ef..da433b271e8b9 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr @@ -1,13 +1,14 @@ error[E0403]: the name `T1` is already used for a generic parameter in this item's generic parameters - --> $DIR/gat-trait-path-generic-type-arg.rs:10:12 + --> $DIR/gat-trait-path-generic-type-arg.rs:11:12 | LL | impl Foo for T { | -- first use of `T1` +LL | LL | type F = &[u8]; | ^^ already used error[E0106]: missing lifetime specifier - --> $DIR/gat-trait-path-generic-type-arg.rs:10:18 + --> $DIR/gat-trait-path-generic-type-arg.rs:11:18 | LL | type F = &[u8]; | ^ expected named lifetime parameter @@ -17,7 +18,13 @@ help: consider introducing a named lifetime parameter LL | type F<'a, T1> = &'a [u8]; | +++ ++ -error: aborting due to 2 previous errors +error[E0207]: the type parameter `T1` is not constrained by the impl trait, self type, or predicates + --> $DIR/gat-trait-path-generic-type-arg.rs:9:10 + | +LL | impl Foo for T { + | ^^ unconstrained type parameter + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0106, E0403. +Some errors have detailed explanations: E0106, E0207, E0403. For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/generic-associated-types/issue-70304.rs b/src/test/ui/generic-associated-types/issue-70304.rs index 1c3d166a1af11..759568d6df7ee 100644 --- a/src/test/ui/generic-associated-types/issue-70304.rs +++ b/src/test/ui/generic-associated-types/issue-70304.rs @@ -2,6 +2,7 @@ trait Document { type Cursor<'a>: DocCursor<'a>; + //~^ ERROR: missing required bound on `Cursor` fn cursor(&self) -> Self::Cursor<'_>; } @@ -45,8 +46,7 @@ where } fn create_doc() -> impl Document = DocCursorImpl<'_>> { - //~^ ERROR: missing lifetime specifier - //~| ERROR: missing lifetime specifier + //~^ ERROR: missing lifetime specifiers DocumentImpl {} } diff --git a/src/test/ui/generic-associated-types/issue-70304.stderr b/src/test/ui/generic-associated-types/issue-70304.stderr index 08efc82c88658..f5821881e7357 100644 --- a/src/test/ui/generic-associated-types/issue-70304.stderr +++ b/src/test/ui/generic-associated-types/issue-70304.stderr @@ -1,26 +1,27 @@ -error[E0106]: missing lifetime specifier - --> $DIR/issue-70304.rs:47:41 +error[E0106]: missing lifetime specifiers + --> $DIR/issue-70304.rs:48:41 | LL | fn create_doc() -> impl Document = DocCursorImpl<'_>> { - | ^^ expected named lifetime parameter + | ^^ ^^ expected named lifetime parameter + | | + | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | -LL | fn create_doc() -> impl Document = DocCursorImpl<'_>> { - | ~~~~~~~ +LL | fn create_doc() -> impl Document = DocCursorImpl<'static>> { + | ~~~~~~~ ~~~~~~~ -error[E0106]: missing lifetime specifier - --> $DIR/issue-70304.rs:47:61 +error: missing required bound on `Cursor` + --> $DIR/issue-70304.rs:4:5 | -LL | fn create_doc() -> impl Document = DocCursorImpl<'_>> { - | ^^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime +LL | type Cursor<'a>: DocCursor<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` | -LL | fn create_doc() -> impl Document = DocCursorImpl<'static>> { - | ~~~~~~~ + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-95305.rs b/src/test/ui/generic-associated-types/issue-95305.rs index 9ead347984b0c..b8e0b9c1cd70e 100644 --- a/src/test/ui/generic-associated-types/issue-95305.rs +++ b/src/test/ui/generic-associated-types/issue-95305.rs @@ -8,10 +8,10 @@ trait Foo { type Item<'a>; } -fn foo(x: &impl Foo = u32>) { } - //~^ ERROR missing lifetime specifier +fn foo(x: &impl Foo = u32>) {} +//~^ ERROR `'_` cannot be used here [E0637] -fn bar(x: &impl for<'a> Foo = &'_ u32>) { } - //~^ ERROR missing lifetime specifier +fn bar(x: &impl for<'a> Foo = &'_ u32>) {} +//~^ ERROR `'_` cannot be used here [E0637] fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-95305.stderr b/src/test/ui/generic-associated-types/issue-95305.stderr index 2b48378dc4350..9e645003e1ee0 100644 --- a/src/test/ui/generic-associated-types/issue-95305.stderr +++ b/src/test/ui/generic-associated-types/issue-95305.stderr @@ -1,25 +1,15 @@ -error[E0106]: missing lifetime specifier +error[E0637]: `'_` cannot be used here --> $DIR/issue-95305.rs:11:26 | -LL | fn foo(x: &impl Foo = u32>) { } - | ^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | fn foo<'a>(x: &impl Foo = u32>) { } - | ++++ ~~ +LL | fn foo(x: &impl Foo = u32>) {} + | ^^ `'_` is a reserved lifetime name -error[E0106]: missing lifetime specifier +error[E0637]: `'_` cannot be used here --> $DIR/issue-95305.rs:14:41 | -LL | fn bar(x: &impl for<'a> Foo = &'_ u32>) { } - | ^^ expected named lifetime parameter - | -help: consider using the `'a` lifetime - | -LL | fn bar(x: &impl for<'a> Foo = &'a u32>) { } - | ~~ +LL | fn bar(x: &impl for<'a> Foo = &'_ u32>) {} + | ^^ `'_` is a reserved lifetime name error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs index 54b483f53d4cb..dac0db39db269 100644 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs @@ -8,7 +8,9 @@ fn should_error() where T : Into<&u32> {} trait X<'a, K: 'a> { fn foo<'b, L: X<&'b Nested>>(); //~^ ERROR missing lifetime specifier [E0106] + //~| ERROR the type `&'b Nested` does not fulfill the required lifetime } fn bar<'b, L: X<&'b Nested>>(){} //~^ ERROR missing lifetime specifier [E0106] +//~| ERROR the type `&'b Nested` does not fulfill the required lifetime diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr index 270d6b8e18e22..09133a98101d8 100644 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr @@ -5,21 +5,10 @@ LL | fn should_error() where T : Into<&u32> {} | ^ explicit lifetime name needed here error[E0106]: missing lifetime specifier - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:17 - | -LL | fn bar<'b, L: X<&'b Nested>>(){} - | ^ expected named lifetime parameter - | -help: consider using the `'b` lifetime - | -LL | fn bar<'b, L: X<'b, &'b Nested>>(){} - | +++ - -error[E0106]: missing lifetime specifier - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:21 + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20 | LL | fn foo<'b, L: X<&'b Nested>>(); - | ^ expected named lifetime parameter + | ^ expected named lifetime parameter | note: these named lifetimes are available to use --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:8:9 @@ -33,7 +22,42 @@ help: consider using one of the available lifetimes here LL | fn foo<'b, L: X<'lifetime, &'b Nested>>(); | ++++++++++ -error: aborting due to 3 previous errors +error[E0106]: missing lifetime specifier + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:14:16 + | +LL | fn bar<'b, L: X<&'b Nested>>(){} + | ^ expected named lifetime parameter + | +help: consider using the `'b` lifetime + | +LL | fn bar<'b, L: X<'b, &'b Nested>>(){} + | +++ + +error[E0477]: the type `&'b Nested` does not fulfill the required lifetime + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:19 + | +LL | fn foo<'b, L: X<&'b Nested>>(); + | ^^^^^^^^^^^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:8:16 + | +LL | trait X<'a, K: 'a> { + | ^^ + +error[E0477]: the type `&'b Nested` does not fulfill the required lifetime + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:14:15 + | +LL | fn bar<'b, L: X<&'b Nested>>(){} + | ^^^^^^^^^^^^^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:8:16 + | +LL | trait X<'a, K: 'a> { + | ^^ + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0106, E0637. +Some errors have detailed explanations: E0106, E0477, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/generics/wrong-number-of-args.rs b/src/test/ui/generics/wrong-number-of-args.rs index 272cd36196804..cd2f96a1819e4 100644 --- a/src/test/ui/generics/wrong-number-of-args.rs +++ b/src/test/ui/generics/wrong-number-of-args.rs @@ -120,6 +120,7 @@ mod r#trait { type B = Box; //~^ ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic type C = Box>; //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied @@ -136,6 +137,7 @@ mod r#trait { type F = Box>; //~^ ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic type G = Box>; //~^ ERROR this trait takes 1 generic argument but 0 generic arguments @@ -161,6 +163,7 @@ mod associated_item { type A = Box>; //~^ ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic type B = Box>; //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied @@ -169,6 +172,7 @@ mod associated_item { type C = Box>; //~^ ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic //~| ERROR this trait takes 0 generic arguments but 1 generic argument //~| HELP remove } @@ -203,6 +207,7 @@ mod associated_item { //~| HELP add missing //~| ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic type B = Box>; //~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied @@ -217,10 +222,12 @@ mod associated_item { type D = Box>; //~^ ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic type E = Box>; //~^ ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic //~| ERROR this trait takes 1 generic argument but 2 generic arguments //~| HELP remove @@ -265,6 +272,7 @@ mod associated_item { type A = Box>; //~^ ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic type B = Box>; //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied @@ -279,6 +287,7 @@ mod associated_item { type A = Box>; //~^ ERROR missing lifetime specifier //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic //~| ERROR this trait takes 1 generic argument but 0 generic arguments //~| HELP add missing diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr index 3b0834a5f51b2..388c23fc24f74 100644 --- a/src/test/ui/generics/wrong-number-of-args.stderr +++ b/src/test/ui/generics/wrong-number-of-args.stderr @@ -1,3 +1,172 @@ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:48:14 + | +LL | type A = Ty; + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Ty<'a>; + | ++++ ++++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:58:16 + | +LL | type C = Ty; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type C<'a> = Ty<'a, usize>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:64:16 + | +LL | type E = Ty<>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type E<'a> = Ty<'a, >; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:120:22 + | +LL | type B = Box; + | ^^^^^^^^^^^^^^^ expected named lifetime parameter + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type B = Box GenericLifetime<'a>>; + | +++++++ ++++ +help: consider introducing a named lifetime parameter + | +LL | type B<'a> = Box>; + | ++++ ++++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:137:37 + | +LL | type F = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type F = Box GenericLifetime<'a, >>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type F<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:163:43 + | +LL | type A = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type A = Box GenericLifetimeAT<'a, AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:172:43 + | +LL | type C = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type C = Box GenericLifetimeAT<'a, (), AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type C<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:205:47 + | +LL | type A = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type A = Box GenericLifetimeTypeAT<'a, AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:222:47 + | +LL | type D = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type D = Box GenericLifetimeTypeAT<'a, (), AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type D<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:227:47 + | +LL | type E = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type E = Box GenericLifetimeTypeAT<'a, (), (), AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type E<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifiers + --> $DIR/wrong-number-of-args.rs:272:51 + | +LL | type A = Box>; + | ^ expected 2 lifetime parameters + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type A = Box GenericLifetimeLifetimeAT<'a, 'a, AssocTy=()>>; + | +++++++ +++++++ +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/wrong-number-of-args.rs:287:55 + | +LL | type A = Box>; + | ^ expected 2 lifetime parameters + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type A = Box GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>; + | +++++++ +++++++ +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++++++ + error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied --> $DIR/wrong-number-of-args.rs:6:14 | @@ -148,17 +317,6 @@ help: add missing generic argument LL | type A = Ty; | ~~~~~ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:48:14 - | -LL | type A = Ty; - | ^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Ty<'a>; - | ++++ ~~~~~~ - error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:54:14 | @@ -175,17 +333,6 @@ help: add missing generic argument LL | type B = Ty<'static, T>; | +++ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:58:17 - | -LL | type C = Ty; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type C<'a> = Ty<'a, usize>; - | ++++ +++ - error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:64:14 | @@ -202,17 +349,6 @@ help: add missing generic argument LL | type E = Ty; | + -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:64:16 - | -LL | type E = Ty<>; - | ^- expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type E<'a> = Ty<'a>; - | ++++ ++ - error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied --> $DIR/wrong-number-of-args.rs:70:14 | @@ -319,19 +455,8 @@ note: trait defined here, with 0 generic parameters LL | trait NonGeneric { | ^^^^^^^^^^ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:120:22 - | -LL | type B = Box; - | ^^^^^^^^^^^^^^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type B<'a> = Box>; - | ++++ ~~~~~~~~~~~~~~~~~~~ - error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied - --> $DIR/wrong-number-of-args.rs:124:22 + --> $DIR/wrong-number-of-args.rs:125:22 | LL | type C = Box>; | ^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument @@ -345,7 +470,7 @@ LL | trait GenericLifetime<'a> { | ^^^^^^^^^^^^^^^ -- error[E0107]: missing generics for trait `GenericType` - --> $DIR/wrong-number-of-args.rs:128:22 + --> $DIR/wrong-number-of-args.rs:129:22 | LL | type D = Box; | ^^^^^^^^^^^ expected 1 generic argument @@ -361,7 +486,7 @@ LL | type D = Box>; | ~~~~~~~~~~~~~~ error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:132:22 + --> $DIR/wrong-number-of-args.rs:133:22 | LL | type E = Box>; | ^^^^^^^^^^^ ----- help: remove this generic argument @@ -374,19 +499,8 @@ note: trait defined here, with 1 generic parameter: `A` LL | trait GenericType { | ^^^^^^^^^^^ - -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:136:37 - | -LL | type F = Box>; - | ^- expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type F<'a> = Box>; - | ++++ ++ - error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:140:22 + --> $DIR/wrong-number-of-args.rs:142:22 | LL | type G = Box>; | ^^^^^^^^^^^ expected 1 generic argument @@ -402,7 +516,7 @@ LL | type G = Box>; | + error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/wrong-number-of-args.rs:151:26 + --> $DIR/wrong-number-of-args.rs:153:26 | LL | type A = Box>; | ^^^^^^^^^^^^------------------- help: remove these generics @@ -410,24 +524,13 @@ LL | type A = Box>; | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/wrong-number-of-args.rs:147:15 + --> $DIR/wrong-number-of-args.rs:149:15 | LL | trait NonGenericAT { | ^^^^^^^^^^^^ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:161:44 - | -LL | type A = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied - --> $DIR/wrong-number-of-args.rs:165:26 + --> $DIR/wrong-number-of-args.rs:168:26 | LL | type B = Box>; | ^^^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument @@ -435,13 +538,13 @@ LL | type B = Box>; | expected 1 lifetime argument | note: trait defined here, with 1 lifetime parameter: `'a` - --> $DIR/wrong-number-of-args.rs:157:15 + --> $DIR/wrong-number-of-args.rs:159:15 | LL | trait GenericLifetimeAT<'a> { | ^^^^^^^^^^^^^^^^^ -- error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/wrong-number-of-args.rs:169:26 + --> $DIR/wrong-number-of-args.rs:172:26 | LL | type C = Box>; | ^^^^^^^^^^^^^^^^^ -- help: remove this generic argument @@ -449,30 +552,19 @@ LL | type C = Box>; | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/wrong-number-of-args.rs:157:15 + --> $DIR/wrong-number-of-args.rs:159:15 | LL | trait GenericLifetimeAT<'a> { | ^^^^^^^^^^^^^^^^^ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:169:44 - | -LL | type C = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type C<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:181:26 + --> $DIR/wrong-number-of-args.rs:185:26 | LL | type A = Box>; | ^^^^^^^^^^^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:177:15 + --> $DIR/wrong-number-of-args.rs:181:15 | LL | trait GenericTypeAT { | ^^^^^^^^^^^^^ - @@ -482,7 +574,7 @@ LL | type A = Box>; | ++ error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:185:26 + --> $DIR/wrong-number-of-args.rs:189:26 | LL | type B = Box>; | ^^^^^^^^^^^^^ -- help: remove this generic argument @@ -490,13 +582,13 @@ LL | type B = Box>; | expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:177:15 + --> $DIR/wrong-number-of-args.rs:181:15 | LL | trait GenericTypeAT { | ^^^^^^^^^^^^^ - error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/wrong-number-of-args.rs:189:26 + --> $DIR/wrong-number-of-args.rs:193:26 | LL | type C = Box>; | ^^^^^^^^^^^^^--------------------- help: remove these generics @@ -504,19 +596,19 @@ LL | type C = Box>; | expected 0 lifetime arguments | note: trait defined here, with 0 lifetime parameters - --> $DIR/wrong-number-of-args.rs:177:15 + --> $DIR/wrong-number-of-args.rs:181:15 | LL | trait GenericTypeAT { | ^^^^^^^^^^^^^ error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:189:26 + --> $DIR/wrong-number-of-args.rs:193:26 | LL | type C = Box>; | ^^^^^^^^^^^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:177:15 + --> $DIR/wrong-number-of-args.rs:181:15 | LL | trait GenericTypeAT { | ^^^^^^^^^^^^^ - @@ -526,13 +618,13 @@ LL | type C = Box>; | +++ error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:201:26 + --> $DIR/wrong-number-of-args.rs:205:26 | LL | type A = Box>; | ^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ - @@ -541,25 +633,14 @@ help: add missing generic argument LL | type A = Box>; | ++ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:201:48 - | -LL | type A = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:207:26 + --> $DIR/wrong-number-of-args.rs:212:26 | LL | type B = Box>; | ^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ - @@ -569,7 +650,7 @@ LL | type B = Box>; | +++ error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied - --> $DIR/wrong-number-of-args.rs:211:26 + --> $DIR/wrong-number-of-args.rs:216:26 | LL | type C = Box>; | ^^^^^^^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument @@ -577,19 +658,19 @@ LL | type C = Box $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ -- error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:211:26 + --> $DIR/wrong-number-of-args.rs:216:26 | LL | type C = Box>; | ^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ - @@ -598,19 +679,8 @@ help: add missing generic argument LL | type C = Box>; | +++ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:217:48 - | -LL | type D = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type D<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:221:26 + --> $DIR/wrong-number-of-args.rs:227:26 | LL | type E = Box>; | ^^^^^^^^^^^^^^^^^^^^^ -- help: remove this generic argument @@ -618,24 +688,13 @@ LL | type E = Box>; | expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ - -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:221:48 - | -LL | type E = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type E<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied - --> $DIR/wrong-number-of-args.rs:227:26 + --> $DIR/wrong-number-of-args.rs:234:26 | LL | type F = Box>; | ^^^^^^^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument @@ -643,13 +702,13 @@ LL | type F = Box $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ -- error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:231:26 + --> $DIR/wrong-number-of-args.rs:238:26 | LL | type G = Box>; | ^^^^^^^^^^^^^^^^^^^^^ -- help: remove this generic argument @@ -657,13 +716,13 @@ LL | type G = Box | expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ - error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied - --> $DIR/wrong-number-of-args.rs:235:26 + --> $DIR/wrong-number-of-args.rs:242:26 | LL | type H = Box>; | ^^^^^^^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument @@ -671,13 +730,13 @@ LL | type H = Box $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ -- error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:235:26 + --> $DIR/wrong-number-of-args.rs:242:26 | LL | type H = Box>; | ^^^^^^^^^^^^^^^^^^^^^ -- help: remove this generic argument @@ -685,19 +744,19 @@ LL | type H = Box $DIR/wrong-number-of-args.rs:197:15 + --> $DIR/wrong-number-of-args.rs:201:15 | LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ - error[E0107]: this trait takes 2 generic arguments but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:247:26 + --> $DIR/wrong-number-of-args.rs:254:26 | LL | type A = Box>; | ^^^^^^^^^^^^^^^^^ expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `A`, `B` - --> $DIR/wrong-number-of-args.rs:243:15 + --> $DIR/wrong-number-of-args.rs:250:15 | LL | trait GenericTypeTypeAT { | ^^^^^^^^^^^^^^^^^ - - @@ -707,7 +766,7 @@ LL | type A = Box>; | +++++ error[E0107]: this trait takes 2 generic arguments but 1 generic argument was supplied - --> $DIR/wrong-number-of-args.rs:251:26 + --> $DIR/wrong-number-of-args.rs:258:26 | LL | type B = Box>; | ^^^^^^^^^^^^^^^^^ -- supplied 1 generic argument @@ -715,7 +774,7 @@ LL | type B = Box>; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `A`, `B` - --> $DIR/wrong-number-of-args.rs:243:15 + --> $DIR/wrong-number-of-args.rs:250:15 | LL | trait GenericTypeTypeAT { | ^^^^^^^^^^^^^^^^^ - - @@ -725,7 +784,7 @@ LL | type B = Box>; | +++ error[E0107]: this trait takes 2 generic arguments but 3 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:255:26 + --> $DIR/wrong-number-of-args.rs:262:26 | LL | type C = Box>; | ^^^^^^^^^^^^^^^^^ -- help: remove this generic argument @@ -733,24 +792,13 @@ LL | type C = Box>; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `A`, `B` - --> $DIR/wrong-number-of-args.rs:243:15 + --> $DIR/wrong-number-of-args.rs:250:15 | LL | trait GenericTypeTypeAT { | ^^^^^^^^^^^^^^^^^ - - -error[E0106]: missing lifetime specifiers - --> $DIR/wrong-number-of-args.rs:265:52 - | -LL | type A = Box>; - | ^ expected 2 lifetime parameters - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Box>; - | ++++ +++++++ - error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/wrong-number-of-args.rs:269:26 + --> $DIR/wrong-number-of-args.rs:277:26 | LL | type B = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ------- supplied 1 lifetime argument @@ -758,7 +806,7 @@ LL | type B = Box>; | expected 2 lifetime arguments | note: trait defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/wrong-number-of-args.rs:261:15 + --> $DIR/wrong-number-of-args.rs:268:15 | LL | trait GenericLifetimeLifetimeAT<'a, 'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- @@ -768,13 +816,13 @@ LL | type B = Box | ++++ error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:279:26 + --> $DIR/wrong-number-of-args.rs:287:26 | LL | type A = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:275:15 + --> $DIR/wrong-number-of-args.rs:283:15 | LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - @@ -783,19 +831,8 @@ help: add missing generic argument LL | type A = Box>; | ++ -error[E0106]: missing lifetime specifiers - --> $DIR/wrong-number-of-args.rs:279:56 - | -LL | type A = Box>; - | ^ expected 2 lifetime parameters - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Box>; - | ++++ +++++++ - error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/wrong-number-of-args.rs:285:26 + --> $DIR/wrong-number-of-args.rs:294:26 | LL | type B = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- supplied 1 lifetime argument @@ -803,7 +840,7 @@ LL | type B = Box | expected 2 lifetime arguments | note: trait defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/wrong-number-of-args.rs:275:15 + --> $DIR/wrong-number-of-args.rs:283:15 | LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- @@ -813,13 +850,13 @@ LL | type B = Box $DIR/wrong-number-of-args.rs:285:26 + --> $DIR/wrong-number-of-args.rs:294:26 | LL | type B = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `A` - --> $DIR/wrong-number-of-args.rs:275:15 + --> $DIR/wrong-number-of-args.rs:283:15 | LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - @@ -829,7 +866,7 @@ LL | type B = Box $DIR/wrong-number-of-args.rs:291:26 + --> $DIR/wrong-number-of-args.rs:300:26 | LL | type C = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- supplied 1 lifetime argument @@ -837,7 +874,7 @@ LL | type C = Box $DIR/wrong-number-of-args.rs:275:15 + --> $DIR/wrong-number-of-args.rs:283:15 | LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- @@ -847,7 +884,7 @@ LL | type C = Box $DIR/wrong-number-of-args.rs:301:18 + --> $DIR/wrong-number-of-args.rs:310:18 | LL | type A = HashMap; | ^^^^^^^ expected at least 2 generic arguments @@ -863,7 +900,7 @@ LL | type A = HashMap; | ~~~~~~~~~~~~~ error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied - --> $DIR/wrong-number-of-args.rs:305:18 + --> $DIR/wrong-number-of-args.rs:314:18 | LL | type B = HashMap; | ^^^^^^^ ------ supplied 1 generic argument @@ -881,7 +918,7 @@ LL | type B = HashMap; | +++ error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/wrong-number-of-args.rs:309:18 + --> $DIR/wrong-number-of-args.rs:318:18 | LL | type C = HashMap<'static>; | ^^^^^^^--------- help: remove these generics @@ -895,7 +932,7 @@ LL | pub struct HashMap { | ^^^^^^^ error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:309:18 + --> $DIR/wrong-number-of-args.rs:318:18 | LL | type C = HashMap<'static>; | ^^^^^^^ expected at least 2 generic arguments @@ -911,7 +948,7 @@ LL | type C = HashMap<'static, K, V>; | ++++++ error[E0107]: this struct takes at most 3 generic arguments but 4 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:315:18 + --> $DIR/wrong-number-of-args.rs:324:18 | LL | type D = HashMap; | ^^^^^^^ --- help: remove this generic argument @@ -925,7 +962,7 @@ LL | pub struct HashMap { | ^^^^^^^ - - --------------- error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:319:18 + --> $DIR/wrong-number-of-args.rs:328:18 | LL | type E = HashMap<>; | ^^^^^^^ expected at least 2 generic arguments @@ -941,7 +978,7 @@ LL | type E = HashMap; | ++++ error[E0107]: missing generics for enum `Result` - --> $DIR/wrong-number-of-args.rs:325:18 + --> $DIR/wrong-number-of-args.rs:334:18 | LL | type A = Result; | ^^^^^^ expected 2 generic arguments @@ -957,7 +994,7 @@ LL | type A = Result; | ~~~~~~~~~~~~ error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied - --> $DIR/wrong-number-of-args.rs:329:18 + --> $DIR/wrong-number-of-args.rs:338:18 | LL | type B = Result; | ^^^^^^ ------ supplied 1 generic argument @@ -975,7 +1012,7 @@ LL | type B = Result; | +++ error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/wrong-number-of-args.rs:333:18 + --> $DIR/wrong-number-of-args.rs:342:18 | LL | type C = Result<'static>; | ^^^^^^--------- help: remove these generics @@ -989,7 +1026,7 @@ LL | pub enum Result { | ^^^^^^ error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:333:18 + --> $DIR/wrong-number-of-args.rs:342:18 | LL | type C = Result<'static>; | ^^^^^^ expected 2 generic arguments @@ -1005,7 +1042,7 @@ LL | type C = Result<'static, T, E>; | ++++++ error[E0107]: this enum takes 2 generic arguments but 3 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:339:18 + --> $DIR/wrong-number-of-args.rs:348:18 | LL | type D = Result; | ^^^^^^ ---- help: remove this generic argument @@ -1019,7 +1056,7 @@ LL | pub enum Result { | ^^^^^^ - - error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied - --> $DIR/wrong-number-of-args.rs:343:18 + --> $DIR/wrong-number-of-args.rs:352:18 | LL | type E = Result<>; | ^^^^^^ expected 2 generic arguments diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr index 6521a67428eb2..4b1d979da36e3 100644 --- a/src/test/ui/issues/issue-13497.stderr +++ b/src/test/ui/issues/issue-13497.stderr @@ -8,7 +8,7 @@ LL | &str help: consider using the `'static` lifetime | LL | &'static str - | ~~~~~~~~ + | +++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr index 18f69bb57755a..1025f690a93bc 100644 --- a/src/test/ui/issues/issue-19707.stderr +++ b/src/test/ui/issues/issue-19707.stderr @@ -8,12 +8,12 @@ LL | type Foo = fn(&u8, &u8) -> &u8; = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html help: consider making the type lifetime-generic with a new `'a` lifetime | -LL | type Foo = for<'a> fn(&'a u8, &'a u8) -> &'a u8; - | +++++++ ++ ++ ++ +LL | type Foo = for<'a> fn(&u8, &u8) -> &'a u8; + | +++++++ ++ help: consider introducing a named lifetime parameter | -LL | type Foo<'a> = fn(&'a u8, &'a u8) -> &'a u8; - | ++++ ++ ++ ++ +LL | type Foo<'a> = fn(&u8, &u8) -> &'a u8; + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-19707.rs:5:27 @@ -22,15 +22,14 @@ LL | fn bar &u8>(f: &F) {} | --- --- ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html help: consider making the bound lifetime-generic with a new `'a` lifetime | -LL | fn bar Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} - | +++++++ ++ ++ ++ +LL | fn bar Fn(&u8, &u8) -> &'a u8>(f: &F) {} + | +++++++ ++ help: consider introducing a named lifetime parameter | -LL | fn bar<'a, F: Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} - | +++ ++ ++ ++ +LL | fn bar<'a, F: Fn(&u8, &u8) -> &'a u8>(f: &F) {} + | +++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr index e5f492af5b366..c034bbd2bbc9e 100644 --- a/src/test/ui/issues/issue-30255.stderr +++ b/src/test/ui/issues/issue-30255.stderr @@ -7,8 +7,8 @@ LL | fn f(a: &S, b: i32) -> &i32 { = help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from help: consider introducing a named lifetime parameter | -LL | fn f<'a>(a: &'a S, b: i32) -> &'a i32 { - | ++++ ++ ++ +LL | fn f<'a>(a: &S, b: i32) -> &'a i32 { + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:14:34 @@ -19,8 +19,8 @@ LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c` help: consider introducing a named lifetime parameter | -LL | fn g<'a>(a: &'a S, b: bool, c: &'a i32) -> &'a i32 { - | ++++ ++ ++ ++ +LL | fn g<'a>(a: &S, b: bool, c: &i32) -> &'a i32 { + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:19:44 @@ -31,8 +31,8 @@ LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d` help: consider introducing a named lifetime parameter | -LL | fn h<'a>(a: &'a bool, b: bool, c: &'a S, d: &'a i32) -> &'a i32 { - | ++++ ++ ++ ++ ++ +LL | fn h<'a>(a: &bool, b: bool, c: &S, d: &i32) -> &'a i32 { + | ++++ ++ error: aborting due to 3 previous errors diff --git a/src/test/ui/lifetimes/issue-26638.rs b/src/test/ui/lifetimes/issue-26638.rs index 72fe4286a06b3..000ab6492bb96 100644 --- a/src/test/ui/lifetimes/issue-26638.rs +++ b/src/test/ui/lifetimes/issue-26638.rs @@ -1,8 +1,11 @@ fn parse_type(iter: Box+'static>) -> &str { iter.next() } //~^ ERROR missing lifetime specifier [E0106] +//~| ERROR mismatched types fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } //~^ ERROR missing lifetime specifier [E0106] +//~| ERROR mismatched types +//~| ERROR this function takes 1 argument but 0 arguments were supplied fn parse_type_3() -> &str { unimplemented!() } //~^ ERROR missing lifetime specifier [E0106] diff --git a/src/test/ui/lifetimes/issue-26638.stderr b/src/test/ui/lifetimes/issue-26638.stderr index bb7cdcbb100ff..3075ee0bae122 100644 --- a/src/test/ui/lifetimes/issue-26638.stderr +++ b/src/test/ui/lifetimes/issue-26638.stderr @@ -11,19 +11,19 @@ LL | fn parse_type<'a>(iter: Box+'static>) -> &'a str { | ++++ ++ error[E0106]: missing lifetime specifier - --> $DIR/issue-26638.rs:4:40 + --> $DIR/issue-26638.rs:5:40 | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } | ^ expected named lifetime parameter | - = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() } - | ~~~~~~~~ + | +++++++ error[E0106]: missing lifetime specifier - --> $DIR/issue-26638.rs:7:22 + --> $DIR/issue-26638.rs:10:22 | LL | fn parse_type_3() -> &str { unimplemented!() } | ^ expected named lifetime parameter @@ -32,8 +32,42 @@ LL | fn parse_type_3() -> &str { unimplemented!() } help: consider using the `'static` lifetime | LL | fn parse_type_3() -> &'static str { unimplemented!() } - | ~~~~~~~~ + | +++++++ + +error[E0308]: mismatched types + --> $DIR/issue-26638.rs:1:69 + | +LL | fn parse_type(iter: Box+'static>) -> &str { iter.next() } + | ---- ^^^^^^^^^^^ expected `&str`, found enum `Option` + | | + | expected `&'static str` because of return type + | + = note: expected reference `&'static str` + found enum `Option<&str>` + +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/issue-26638.rs:5:47 + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } + | ^^^^-- an argument of type `&u8` is missing + | +help: provide the argument + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter({&u8}) } + | ~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/issue-26638.rs:5:47 + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } + | ---- ^^^^^^ expected `str`, found `u8` + | | + | expected `&'static str` because of return type + | + = note: expected reference `&'static str` + found reference `&u8` -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0061, E0106, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 0e69cd50f6a82..81d6192c74f7d 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -8,7 +8,7 @@ LL | fn f() -> &isize { help: consider using the `'static` lifetime | LL | fn f() -> &'static isize { - | ~~~~~~~~ + | +++++++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33 @@ -19,8 +19,8 @@ LL | fn g(_x: &isize, _y: &isize) -> &isize { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y` help: consider introducing a named lifetime parameter | -LL | fn g<'a>(_x: &'a isize, _y: &'a isize) -> &'a isize { - | ++++ ++ ++ ++ +LL | fn g<'a>(_x: &isize, _y: &isize) -> &'a isize { + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19 @@ -31,8 +31,8 @@ LL | fn h(_x: &Foo) -> &isize { = help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from help: consider introducing a named lifetime parameter | -LL | fn h<'a>(_x: &'a Foo) -> &'a isize { - | ++++ ++ ++ +LL | fn h<'a>(_x: &Foo) -> &'a isize { + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20 @@ -40,11 +40,11 @@ error[E0106]: missing lifetime specifier LL | fn i(_x: isize) -> &isize { | ^ expected named lifetime parameter | - = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | LL | fn i(_x: isize) -> &'static isize { - | ~~~~~~~~ + | +++++++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:34:24 @@ -52,11 +52,11 @@ error[E0106]: missing lifetime specifier LL | fn j(_x: StaticStr) -> &isize { | ^ expected named lifetime parameter | - = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | LL | fn j(_x: StaticStr) -> &'static isize { - | ~~~~~~~~ + | +++++++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:40:49 @@ -64,11 +64,11 @@ error[E0106]: missing lifetime specifier LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { | ^ expected named lifetime parameter | - = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments -help: consider using the `'a` lifetime + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime | -LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &'a isize { - | ~~~ +LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &'static isize { + | +++++++ error: aborting due to 6 previous errors diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs index d1263a4acb28a..99c29202e9d83 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs +++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs @@ -1,5 +1,8 @@ -fn foo(x: &i32, y: &i32) -> &i32 { //~ ERROR missing lifetime +fn foo(x: &i32, y: &i32) -> &i32 { + //~^ ERROR missing lifetime if x > y { x } else { y } + //~^ ERROR lifetime of reference outlives + //~| ERROR lifetime of reference outlives } -fn main() { } +fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index bcc3e9510ac97..9a0c14bfe8efa 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -7,9 +7,36 @@ LL | fn foo(x: &i32, y: &i32) -> &i32 { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` help: consider introducing a named lifetime parameter | -LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { - | ++++ ++ ++ ++ +LL | fn foo<'a>(x: &i32, y: &i32) -> &'a i32 { + | ++++ ++ -error: aborting due to previous error +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1b-return-no-names-if-else.rs:3:16 + | +LL | if x > y { x } else { y } + | ^ + | + = note: ...the reference is valid for the static lifetime... +note: ...but the borrowed content is only valid for the anonymous lifetime defined here + --> $DIR/ex1b-return-no-names-if-else.rs:1:11 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | ^^^^ + +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1b-return-no-names-if-else.rs:3:27 + | +LL | if x > y { x } else { y } + | ^ + | + = note: ...the reference is valid for the static lifetime... +note: ...but the borrowed content is only valid for the anonymous lifetime defined here + --> $DIR/ex1b-return-no-names-if-else.rs:1:20 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | ^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0312. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr b/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr index b16b792aefee9..b8c68a4607da8 100644 --- a/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr +++ b/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr @@ -7,7 +7,7 @@ LL | type B<'a> = as Trait>::Foo; help: consider using the `'a` lifetime | LL | type B<'a> = as Trait<'a>>::Foo; - | ~~~~~~~~~ + | ++++ error[E0106]: missing lifetime specifier --> $DIR/missing-lifetime-in-alias.rs:26:28 @@ -20,6 +20,10 @@ note: these named lifetimes are available to use | LL | type C<'a, 'b> = as Trait>::Bar; | ^^ ^^ +help: consider using one of the available lifetimes here + | +LL | type C<'a, 'b> = as Trait<'lifetime>>::Bar; + | +++++++++++ error[E0107]: missing generics for associated type `Trait::Bar` --> $DIR/missing-lifetime-in-alias.rs:26:36 diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs index 6aa34354a7ad9..c7842667dc614 100644 --- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs +++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs @@ -9,6 +9,7 @@ impl> Iterator for ChunkingIterator { type Item = IteratorChunk; //~ ERROR missing lifetime fn next(&mut self) -> Option> { + //~^ ERROR `impl` item signature doesn't match `trait` item signature todo!() } } diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr index c7e1f87f2d4d4..94a9c97576f67 100644 --- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr +++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr @@ -1,14 +1,30 @@ error[E0106]: missing lifetime specifier - --> $DIR/issue-74918-missing-lifetime.rs:9:31 + --> $DIR/issue-74918-missing-lifetime.rs:9:30 | LL | type Item = IteratorChunk; - | ^ expected named lifetime parameter + | ^ expected named lifetime parameter | help: consider introducing a named lifetime parameter | LL | type Item<'a> = IteratorChunk<'a, T, S>; | ++++ +++ -error: aborting due to previous error +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/issue-74918-missing-lifetime.rs:11:5 + | +LL | fn next(&mut self) -> Option> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 mut ChunkingIterator) -> Option>` + | + ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn next(&mut self) -> Option; + | ----------------------------------------- expected `fn(&'1 mut ChunkingIterator) -> Option>` + | + = note: expected `fn(&'1 mut ChunkingIterator) -> Option>` + found `fn(&'1 mut ChunkingIterator) -> Option>` + = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs index 4397baea4a940..c377ecea94d0c 100644 --- a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs @@ -2,5 +2,5 @@ fn main() {} trait Foo { fn fn_with_type_named_same_as_local_in_param(b: b); - //~^ ERROR cannot find type `b` in this scope + //~^ ERROR cannot find type `b` in this scope [E0412] } diff --git a/src/test/ui/rfc1623-2.rs b/src/test/ui/rfc1623-2.rs index 35a2ef10c2e3c..b33594dea190f 100644 --- a/src/test/ui/rfc1623-2.rs +++ b/src/test/ui/rfc1623-2.rs @@ -9,5 +9,6 @@ static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = //~^ ERROR missing lifetime specifier [E0106] &(non_elidable as fn(&u8, &u8) -> &u8); //~^ ERROR missing lifetime specifier [E0106] + //~| ERROR mismatched types fn main() {} diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfc1623-2.stderr index 65b9f68817aa4..f69d194f5c844 100644 --- a/src/test/ui/rfc1623-2.stderr +++ b/src/test/ui/rfc1623-2.stderr @@ -8,8 +8,8 @@ LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html help: consider making the type lifetime-generic with a new `'a` lifetime | -LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = - | +++++++ ++ ++ ++ +LL | static NON_ELIDABLE_FN: &for<'a> fn(&u8, &u8) -> &'a u8 = + | +++++++ ++ error[E0106]: missing lifetime specifier --> $DIR/rfc1623-2.rs:10:39 @@ -18,12 +18,21 @@ LL | &(non_elidable as fn(&u8, &u8) -> &u8); | --- --- ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html help: consider making the type lifetime-generic with a new `'a` lifetime | -LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); - | +++++++ ++ ++ ++ +LL | &(non_elidable as for<'a> fn(&u8, &u8) -> &'a u8); + | +++++++ ++ + +error[E0308]: mismatched types + --> $DIR/rfc1623-2.rs:10:7 + | +LL | &(non_elidable as fn(&u8, &u8) -> &u8); + | ^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's> fn(&'r u8, &'s u8) -> &u8` + found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0308. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr index a761ec5916745..87aad3ad66ee2 100644 --- a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr +++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr @@ -21,15 +21,14 @@ LL | struct S2 &i32>(F); | ---- ---- ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html help: consider making the bound lifetime-generic with a new `'a` lifetime | -LL | struct S2 Fn(&'a i32, &'a i32) -> &'a i32>(F); - | +++++++ ++ ++ ++ +LL | struct S2 Fn(&i32, &i32) -> &'a i32>(F); + | +++++++ ++ help: consider introducing a named lifetime parameter | -LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F); - | +++ ++ ++ ++ +LL | struct S2<'a, F: Fn(&i32, &i32) -> &'a i32>(F); + | +++ ++ error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types --> $DIR/fn-missing-lifetime-in-item.rs:3:40 diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime.rs index 22dc448c97ff0..b2c398acc013d 100644 --- a/src/test/ui/suggestions/impl-trait-missing-lifetime.rs +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime.rs @@ -1,2 +1,2 @@ -fn f(_: impl Iterator) {} //~ ERROR missing lifetime specifier +fn f(_: impl Iterator) {} //~ ERROR `'_` cannot be used here [E0637] fn main() {} diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr index a3a339b13c478..4bd031515038d 100644 --- a/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -1,14 +1,9 @@ -error[E0106]: missing lifetime specifier +error[E0637]: `'_` cannot be used here --> $DIR/impl-trait-missing-lifetime.rs:1:31 | LL | fn f(_: impl Iterator) {} - | ^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | fn f<'a>(_: impl Iterator) {} - | ++++ ~~ + | ^^ `'_` is a reserved lifetime name error: aborting due to previous error -For more information about this error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/suggestions/issue-84592.stderr b/src/test/ui/suggestions/issue-84592.stderr index 70c96feb1de4c..60916757cdb01 100644 --- a/src/test/ui/suggestions/issue-84592.stderr +++ b/src/test/ui/suggestions/issue-84592.stderr @@ -9,8 +9,8 @@ LL | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` help: consider introducing a named lifetime parameter | -LL | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> { - | ++++ ++ ++ ~~ ~~ +LL | fn two_lifetimes_needed<'a>(a: &(), b: &()) -> TwoLifetimes<'a, 'a> { + | ++++ ~~ ~~ error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-86667.rs b/src/test/ui/suggestions/issue-86667.rs index 6aceb13746937..6f8a9938d530e 100644 --- a/src/test/ui/suggestions/issue-86667.rs +++ b/src/test/ui/suggestions/issue-86667.rs @@ -5,12 +5,14 @@ async fn a(s1: &str, s2: &str) -> &str { //~^ ERROR: missing lifetime specifier [E0106] +//~| ERROR: `s1` has an anonymous lifetime `'_` but it needs to satisfy a `'static` s1 } fn b(s1: &str, s2: &str) -> &str { //~^ ERROR: missing lifetime specifier [E0106] s1 + //~^ ERROR: lifetime of reference outlives lifetime of borrowed content... } fn main() {} diff --git a/src/test/ui/suggestions/issue-86667.stderr b/src/test/ui/suggestions/issue-86667.stderr index 14dbbfffb0e62..623d277862bb3 100644 --- a/src/test/ui/suggestions/issue-86667.stderr +++ b/src/test/ui/suggestions/issue-86667.stderr @@ -7,11 +7,11 @@ LL | async fn a(s1: &str, s2: &str) -> &str { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2` help: consider introducing a named lifetime parameter | -LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str { - | ++++ ++ ++ ++ +LL | async fn a<'a>(s1: &str, s2: &str) -> &'a str { + | ++++ ++ error[E0106]: missing lifetime specifier - --> $DIR/issue-86667.rs:11:29 + --> $DIR/issue-86667.rs:12:29 | LL | fn b(s1: &str, s2: &str) -> &str { | ---- ---- ^ expected named lifetime parameter @@ -19,9 +19,34 @@ LL | fn b(s1: &str, s2: &str) -> &str { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2` help: consider introducing a named lifetime parameter | -LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str { - | ++++ ++ ++ ++ +LL | fn b<'a>(s1: &str, s2: &str) -> &'a str { + | ++++ ++ -error: aborting due to 2 previous errors +error[E0759]: `s1` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/issue-86667.rs:6:12 + | +LL | async fn a(s1: &str, s2: &str) -> &str { + | ^^ ---- this data with an anonymous lifetime `'_`... + | | + | ...is used here... +... +LL | s1 + | -- ...and is required to live as long as `'static` here + +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/issue-86667.rs:14:5 + | +LL | s1 + | ^^ + | + = note: ...the reference is valid for the static lifetime... +note: ...but the borrowed content is only valid for the anonymous lifetime defined here + --> $DIR/issue-86667.rs:12:10 + | +LL | fn b(s1: &str, s2: &str) -> &str { + | ^^^^ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0312, E0759. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed index 3c06f4f88c1f9..ed1146dc86617 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed @@ -1,7 +1,7 @@ // run-rustfix // https://github.com/rust-lang/rust/issues/95616 -fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { //~ERROR [E0106] +fn buggy_const<'a, const N: usize>(_a: &Option<[u8; N]>, _f: &str) -> &'a str { //~ERROR [E0106] return ""; } diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr index 7b126c90ee797..17446ae29f98a 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr @@ -7,8 +7,8 @@ LL | fn buggy_const(_a: &Option<[u8; N]>, _f: &str) -> &str { = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_a` or `_f` help: consider introducing a named lifetime parameter | -LL | fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { - | +++ ++ ++ ++ +LL | fn buggy_const<'a, const N: usize>(_a: &Option<[u8; N]>, _f: &str) -> &'a str { + | +++ ++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr index 1ecaade93c8ca..233f1bc5a86ee 100644 --- a/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr +++ b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr @@ -4,10 +4,6 @@ error[E0106]: missing lifetime specifier LL | const A: &str = ""; | ^ expected named lifetime parameter | -help: consider using the `'static` lifetime - | -LL | const A: &'static str = ""; - | +++++++ help: consider introducing a named lifetime parameter | LL ~ trait ZstAssert<'a>: Sized { @@ -20,10 +16,6 @@ error[E0106]: missing lifetime specifier LL | const B: S = S { s: &() }; | ^ expected named lifetime parameter | -help: consider using the `'static` lifetime - | -LL | const B: S<'static> = S { s: &() }; - | +++++++++ help: consider introducing a named lifetime parameter | LL ~ trait ZstAssert<'a>: Sized { @@ -37,10 +29,6 @@ error[E0106]: missing lifetime specifier LL | const C: &'_ str = ""; | ^^ expected named lifetime parameter | -help: consider using the `'static` lifetime - | -LL | const C: &'static str = ""; - | ~~~~~~~ help: consider introducing a named lifetime parameter | LL ~ trait ZstAssert<'a>: Sized { @@ -55,10 +43,6 @@ error[E0106]: missing lifetime specifiers LL | const D: T = T { a: &(), b: &() }; | ^ expected 2 lifetime parameters | -help: consider using the `'static` lifetime - | -LL | const D: T<'static, 'static> = T { a: &(), b: &() }; - | ++++++++++++++++++ help: consider introducing a named lifetime parameter | LL ~ trait ZstAssert<'a>: Sized { diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.rs b/src/test/ui/suggestions/missing-lifetime-specifier.rs index ce847c86bedde..24f5f782f3521 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.rs +++ b/src/test/ui/suggestions/missing-lifetime-specifier.rs @@ -21,22 +21,18 @@ thread_local! { } thread_local! { static b: RefCell>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime specifier - //~| ERROR missing lifetime specifier - //~| ERROR missing lifetime specifier - //~| ERROR missing lifetime specifier + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers } thread_local! { static c: RefCell>>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime - //~| ERROR missing lifetime + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers } thread_local! { static d: RefCell>>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime - //~| ERROR missing lifetime - //~| ERROR missing lifetime - //~| ERROR missing lifetime + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers } thread_local! { diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr index b04ea1c9158df..9354f7883b619 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -8,7 +8,7 @@ LL | static a: RefCell>>> = RefCell::new(HashMap:: help: consider using the `'static` lifetime | LL | static a: RefCell>>>> = RefCell::new(HashMap::new()); - | ~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++ error[E0106]: missing lifetime specifiers --> $DIR/missing-lifetime-specifier.rs:18:44 @@ -23,38 +23,28 @@ LL | | } | = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from -error[E0106]: missing lifetime specifier +error[E0106]: missing lifetime specifiers --> $DIR/missing-lifetime-specifier.rs:23:44 | LL | static b: RefCell>>> = RefCell::new(HashMap::new()); - | ^ expected named lifetime parameter + | ^^^^ expected 2 lifetime parameters + | | + | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | -LL | static b: RefCell>>> = RefCell::new(HashMap::new()); - | ~~~~~~~~ +LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++ ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:23:45 - | -LL | static b: RefCell>>> = RefCell::new(HashMap::new()); - | ^^^ expected 2 lifetime parameters - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime - | -LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); - | ~~~~~~~~~~~~~~~~~~~~~ - -error[E0106]: missing lifetime specifier --> $DIR/missing-lifetime-specifier.rs:23:44 | LL | / thread_local! { LL | | static b: RefCell>>> = RefCell::new(HashMap::new()); - | | ^ expected named lifetime parameter -LL | | -LL | | + | | ^^^^ expected 2 lifetime parameters + | | | + | | expected named lifetime parameter LL | | LL | | LL | | } @@ -63,25 +53,10 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:23:45 - | -LL | / thread_local! { -LL | | static b: RefCell>>> = RefCell::new(HashMap::new()); - | | ^^^ expected 2 lifetime parameters -LL | | -LL | | -LL | | -LL | | -LL | | } - | |_- - | - = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from - -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:30:48 + --> $DIR/missing-lifetime-specifier.rs:28:47 | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); - | ^ expected 2 lifetime parameters + | ^ expected 2 lifetime parameters | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime @@ -90,11 +65,11 @@ LL | static c: RefCell>>>> = | +++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:30:48 + --> $DIR/missing-lifetime-specifier.rs:28:47 | LL | / thread_local! { LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); - | | ^ expected 2 lifetime parameters + | | ^ expected 2 lifetime parameters LL | | LL | | LL | | } @@ -102,38 +77,28 @@ LL | | } | = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:35:44 - | -LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime - | -LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | ~~~~~~~~ - error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:35:49 + --> $DIR/missing-lifetime-specifier.rs:33:44 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | ^ expected 2 lifetime parameters + | ^ ^ expected 2 lifetime parameters + | | + | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | -LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | +++++++++++++++++ +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++ +++++++++++++++++ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:35:44 +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:33:44 | LL | / thread_local! { LL | | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | | ^ expected named lifetime parameter -LL | | -LL | | + | | ^ ^ expected 2 lifetime parameters + | | | + | | expected named lifetime parameter LL | | LL | | LL | | } @@ -141,23 +106,35 @@ LL | | } | = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:35:49 +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:47:44 | LL | / thread_local! { -LL | | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | | ^ expected 2 lifetime parameters -LL | | +LL | | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | | ^ expected named lifetime parameter LL | | LL | | +... | LL | | LL | | } | |_- | - = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:43:44 + --> $DIR/missing-lifetime-specifier.rs:39:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -175,7 +152,7 @@ LL | static e: RefCell>>>> = RefC | ++++ error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:43:44 + --> $DIR/missing-lifetime-specifier.rs:39:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -193,7 +170,7 @@ LL | static e: RefCell>>>> = RefC | ++++ error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:43:44 + --> $DIR/missing-lifetime-specifier.rs:39:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -211,7 +188,7 @@ LL | static e: RefCell>>>> = RefC | ++++ error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:43:44 + --> $DIR/missing-lifetime-specifier.rs:39:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -229,7 +206,7 @@ LL | static e: RefCell>>>> = RefC | ++++ error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:43:44 + --> $DIR/missing-lifetime-specifier.rs:39:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -247,7 +224,7 @@ LL | static e: RefCell>>>> = RefC | ++++ error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:51:45 + --> $DIR/missing-lifetime-specifier.rs:47:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -264,20 +241,8 @@ help: add missing lifetime argument LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ++++ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:51:44 - | -LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); - | ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime - | -LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); - | ~~~~~~~~ - error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:51:45 + --> $DIR/missing-lifetime-specifier.rs:47:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -294,23 +259,8 @@ help: add missing lifetime argument LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ++++ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:51:44 - | -LL | / thread_local! { -LL | | static f: RefCell>>>> = RefCell::new(HashMap::new()); - | | ^ expected named lifetime parameter -LL | | -LL | | -... | -LL | | -LL | | } - | |_- - | - = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from - error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:51:45 + --> $DIR/missing-lifetime-specifier.rs:47:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -328,7 +278,7 @@ LL | static f: RefCell>>>> = Ref | ++++ error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:51:45 + --> $DIR/missing-lifetime-specifier.rs:47:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -346,7 +296,7 @@ LL | static f: RefCell>>>> = Ref | ++++ error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:51:45 + --> $DIR/missing-lifetime-specifier.rs:47:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -363,7 +313,7 @@ help: add missing lifetime argument LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ++++ -error: aborting due to 24 previous errors +error: aborting due to 20 previous errors Some errors have detailed explanations: E0106, E0107. For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.rs b/src/test/ui/suggestions/missing-lt-for-hrtb.rs index a90a90122ad19..5aaa2259e22b2 100644 --- a/src/test/ui/suggestions/missing-lt-for-hrtb.rs +++ b/src/test/ui/suggestions/missing-lt-for-hrtb.rs @@ -1,15 +1,15 @@ struct X<'a>(&'a ()); struct S<'a>(&'a dyn Fn(&X) -> &X); -//~^ ERROR missing lifetime specifier -//~| ERROR missing lifetime specifier +//~^ ERROR missing lifetime specifiers struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); -//~^ ERROR missing lifetime specifier -//~| ERROR missing lifetime specifier +//~^ ERROR missing lifetime specifiers fn main() { let x = S(&|x| { println!("hi"); x + //~^ ERROR lifetime of reference outlives lifetime of borrowed content... [E0312] + //~| ERROR mismatched types }); x.0(&X(&())); } diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr index 33f9d092e6ee0..a1b54b97c3e06 100644 --- a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr +++ b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr @@ -1,67 +1,77 @@ -error[E0106]: missing lifetime specifier +error[E0106]: missing lifetime specifiers --> $DIR/missing-lt-for-hrtb.rs:2:32 | LL | struct S<'a>(&'a dyn Fn(&X) -> &X); - | -- ^ expected named lifetime parameter + | -- ^^ expected named lifetime parameter + | | + | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html -help: consider making the bound lifetime-generic with a new `'b` lifetime - | -LL | struct S<'a>(&'a dyn for<'b> Fn(&'b X) -> &'b X); - | +++++++ ~~~~~ ~~~ -help: consider using the `'a` lifetime - | -LL | struct S<'a>(&'a dyn Fn(&X) -> &'a X); - | ~~~ - -error[E0106]: missing lifetime specifier - --> $DIR/missing-lt-for-hrtb.rs:2:33 - | -LL | struct S<'a>(&'a dyn Fn(&X) -> &X); - | -- ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from - = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html -help: consider making the bound lifetime-generic with a new `'b` lifetime - | -LL | struct S<'a>(&'a dyn for<'b> Fn(&'b X) -> &X<'b>); - | +++++++ ~~~~~ ~~~~~ help: consider using the `'a` lifetime | -LL | struct S<'a>(&'a dyn Fn(&X) -> &X<'a>); - | ~~~~~ +LL | struct S<'a>(&'a dyn Fn(&X) -> &'a X<'a>); + | ++ ++++ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lt-for-hrtb.rs:5:40 +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lt-for-hrtb.rs:4:40 | LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); - | -- ^ expected named lifetime parameter + | -- ^^ expected named lifetime parameter + | | + | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from note: these named lifetimes are available to use - --> $DIR/missing-lt-for-hrtb.rs:5:10 + --> $DIR/missing-lt-for-hrtb.rs:4:10 | LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); | ^^ ^^ help: consider using one of the available lifetimes here | -LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X); - | +++++++++ +LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X<'lifetime>); + | +++++++++ +++++++++++ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lt-for-hrtb.rs:5:41 +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/missing-lt-for-hrtb.rs:10:9 | -LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); - | -- ^ expected named lifetime parameter +LL | x + | ^ | - = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from -note: these named lifetimes are available to use - --> $DIR/missing-lt-for-hrtb.rs:5:10 + = note: ...the reference is valid for the static lifetime... +note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined here + --> $DIR/missing-lt-for-hrtb.rs:8:16 | -LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); - | ^^ ^^ +LL | let x = S(&|x| { + | ________________^ +LL | | println!("hi"); +LL | | x +LL | | +LL | | +LL | | }); + | |_____^ + +error[E0308]: mismatched types + --> $DIR/missing-lt-for-hrtb.rs:10:9 + | +LL | x + | ^ lifetime mismatch + | + = note: expected reference `&'static X<'static>` + found reference `&'static X<'_>` +note: the anonymous lifetime #2 defined here... + --> $DIR/missing-lt-for-hrtb.rs:8:16 + | +LL | let x = S(&|x| { + | ________________^ +LL | | println!("hi"); +LL | | x +LL | | +LL | | +LL | | }); + | |_____^ + = note: ...does not necessarily outlive the static lifetime error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0308, E0312. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/return-elided-lifetime.rs b/src/test/ui/suggestions/return-elided-lifetime.rs index ca336bbb056d5..012d5492a0404 100644 --- a/src/test/ui/suggestions/return-elided-lifetime.rs +++ b/src/test/ui/suggestions/return-elided-lifetime.rs @@ -6,32 +6,27 @@ fn f1() -> &i32 { loop {} } //~^ ERROR missing lifetime specifier [E0106] fn f1_() -> (&i32, &i32) { loop {} } -//~^ ERROR missing lifetime specifier [E0106] -//~^^ ERROR missing lifetime specifier [E0106] +//~^ ERROR missing lifetime specifiers [E0106] fn f2(a: i32, b: i32) -> &i32 { loop {} } //~^ ERROR missing lifetime specifier [E0106] fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} } -//~^ ERROR missing lifetime specifier [E0106] -//~^^ ERROR missing lifetime specifier [E0106] +//~^ ERROR missing lifetime specifiers [E0106] struct S<'a, 'b> { a: &'a i32, b: &'b i32 } fn f3(s: &S) -> &i32 { loop {} } //~^ ERROR missing lifetime specifier [E0106] fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } -//~^ ERROR missing lifetime specifier [E0106] -//~^^ ERROR missing lifetime specifier [E0106] +//~^ ERROR missing lifetime specifiers [E0106] fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } //~^ ERROR missing lifetime specifier [E0106] fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } -//~^ ERROR missing lifetime specifier [E0106] -//~^^ ERROR missing lifetime specifier [E0106] +//~^ ERROR missing lifetime specifiers [E0106] fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} } //~^ ERROR missing lifetime specifier [E0106] fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} } -//~^ ERROR missing lifetime specifier [E0106] -//~^^ ERROR missing lifetime specifier [E0106] +//~^ ERROR missing lifetime specifiers [E0106] fn main() {} diff --git a/src/test/ui/suggestions/return-elided-lifetime.stderr b/src/test/ui/suggestions/return-elided-lifetime.stderr index f147b4463e2f2..1d2ec58bf8704 100644 --- a/src/test/ui/suggestions/return-elided-lifetime.stderr +++ b/src/test/ui/suggestions/return-elided-lifetime.stderr @@ -8,70 +8,50 @@ LL | fn f1() -> &i32 { loop {} } help: consider using the `'static` lifetime | LL | fn f1() -> &'static i32 { loop {} } - | ~~~~~~~~ + | +++++++ -error[E0106]: missing lifetime specifier +error[E0106]: missing lifetime specifiers --> $DIR/return-elided-lifetime.rs:8:14 | LL | fn f1_() -> (&i32, &i32) { loop {} } - | ^ expected named lifetime parameter + | ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | -LL | fn f1_() -> (&'static i32, &i32) { loop {} } - | ~~~~~~~~ +LL | fn f1_() -> (&'static i32, &'static i32) { loop {} } + | +++++++ +++++++ error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:8:20 - | -LL | fn f1_() -> (&i32, &i32) { loop {} } - | ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime - | -LL | fn f1_() -> (&i32, &'static i32) { loop {} } - | ~~~~~~~~ - -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:12:26 + --> $DIR/return-elided-lifetime.rs:11:26 | LL | fn f2(a: i32, b: i32) -> &i32 { loop {} } | ^ expected named lifetime parameter | - = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | LL | fn f2(a: i32, b: i32) -> &'static i32 { loop {} } - | ~~~~~~~~ - -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:14:28 - | -LL | fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} } - | ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments -help: consider using the `'static` lifetime - | -LL | fn f2_(a: i32, b: i32) -> (&'static i32, &i32) { loop {} } - | ~~~~~~~~ + | +++++++ -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:14:34 +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:13:28 | LL | fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} } - | ^ expected named lifetime parameter + | ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter | - = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime | -LL | fn f2_(a: i32, b: i32) -> (&i32, &'static i32) { loop {} } - | ~~~~~~~~ +LL | fn f2_(a: i32, b: i32) -> (&'static i32, &'static i32) { loop {} } + | +++++++ +++++++ error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:19:17 + --> $DIR/return-elided-lifetime.rs:17:17 | LL | fn f3(s: &S) -> &i32 { loop {} } | -- ^ expected named lifetime parameter @@ -79,86 +59,51 @@ LL | fn f3(s: &S) -> &i32 { loop {} } = help: this function's return type contains a borrowed value, but the signature does not say which one of `s`'s 3 lifetimes it is borrowed from help: consider introducing a named lifetime parameter | -LL | fn f3<'a>(s: &'a S) -> &'a i32 { loop {} } - | ++++ ++ ++ - -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:21:26 - | -LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } - | -- -- ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `s`'s 3 lifetimes or one of `t`'s 3 lifetimes -help: consider introducing a named lifetime parameter - | -LL | fn f3_<'a>(s: &'a S, t: &'a S) -> (&'a i32, &i32) { loop {} } - | ++++ ++ ++ ++ +LL | fn f3<'a>(s: &S) -> &'a i32 { loop {} } + | ++++ ++ -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:21:32 +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:19:26 | LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } - | -- -- ^ expected named lifetime parameter + | -- -- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `s`'s 3 lifetimes or one of `t`'s 3 lifetimes help: consider introducing a named lifetime parameter | -LL | fn f3_<'a>(s: &'a S, t: &'a S) -> (&i32, &'a i32) { loop {} } - | ++++ ++ ++ ++ +LL | fn f3_<'a>(s: &S, t: &S) -> (&'a i32, &'a i32) { loop {} } + | ++++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:25:42 + --> $DIR/return-elided-lifetime.rs:22:42 | LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } | ------- ------- ^ expected named lifetime parameter | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` -note: these named lifetimes are available to use - --> $DIR/return-elided-lifetime.rs:25:7 - | -LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } - | ^^ ^^ -help: consider using one of the available lifetimes here - | -LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &'lifetime i32 { loop {} } - | +++++++++ - -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:27:44 - | -LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } - | ------- ------- ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` -note: these named lifetimes are available to use - --> $DIR/return-elided-lifetime.rs:27:8 - | -LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } - | ^^ ^^ -help: consider using one of the available lifetimes here + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime | -LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&'lifetime i32, &i32) { loop {} } - | +++++++++ +LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &'static i32 { loop {} } + | +++++++ -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:27:50 +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:24:44 | LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } - | ------- ------- ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` -note: these named lifetimes are available to use - --> $DIR/return-elided-lifetime.rs:27:8 + | ------- ------- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter | -LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } - | ^^ ^^ -help: consider using one of the available lifetimes here + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'static` lifetime | -LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &'lifetime i32) { loop {} } - | +++++++++ +LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&'static i32, &'static i32) { loop {} } + | +++++++ +++++++ error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:31:35 + --> $DIR/return-elided-lifetime.rs:27:35 | LL | fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} } | ------- ---- ^ expected named lifetime parameter @@ -167,32 +112,22 @@ LL | fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} } help: consider using the `'a` lifetime | LL | fn f5<'a>(a: &'a i32, b: &i32) -> &'a i32 { loop {} } - | ~~~ + | ++ -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:33:37 - | -LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} } - | ------- ---- ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` -help: consider using the `'a` lifetime - | -LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&'a i32, &i32) { loop {} } - | ~~~ - -error[E0106]: missing lifetime specifier - --> $DIR/return-elided-lifetime.rs:33:43 +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:29:37 | LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} } - | ------- ---- ^ expected named lifetime parameter + | ------- ---- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` help: consider using the `'a` lifetime | -LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &'a i32) { loop {} } - | ~~~ +LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&'a i32, &'a i32) { loop {} } + | ++ ++ -error: aborting due to 15 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/return-without-lifetime.rs b/src/test/ui/suggestions/return-without-lifetime.rs index 9bfce11be9ea3..6e3e71884a052 100644 --- a/src/test/ui/suggestions/return-without-lifetime.rs +++ b/src/test/ui/suggestions/return-without-lifetime.rs @@ -1,6 +1,7 @@ struct Thing<'a>(&'a ()); struct Foo<'a>(&usize); //~^ ERROR missing lifetime specifier +//~| ERROR parameter `'a` is never used [E0392] fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } //~^ ERROR missing lifetime specifier diff --git a/src/test/ui/suggestions/return-without-lifetime.stderr b/src/test/ui/suggestions/return-without-lifetime.stderr index 449a61d48090c..f5f99f002739b 100644 --- a/src/test/ui/suggestions/return-without-lifetime.stderr +++ b/src/test/ui/suggestions/return-without-lifetime.stderr @@ -7,10 +7,10 @@ LL | struct Foo<'a>(&usize); help: consider using the `'a` lifetime | LL | struct Foo<'a>(&'a usize); - | ~~~ + | ++ error[E0106]: missing lifetime specifier - --> $DIR/return-without-lifetime.rs:5:34 + --> $DIR/return-without-lifetime.rs:6:34 | LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } | --------- ^ expected named lifetime parameter @@ -19,10 +19,10 @@ LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } help: consider using the `'a` lifetime | LL | fn func1<'a>(_arg: &'a Thing) -> &'a () { unimplemented!() } - | ~~~ + | ++ error[E0106]: missing lifetime specifier - --> $DIR/return-without-lifetime.rs:7:35 + --> $DIR/return-without-lifetime.rs:8:35 | LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } | ---------- ^ expected named lifetime parameter @@ -31,8 +31,17 @@ LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } help: consider using the `'a` lifetime | LL | fn func2<'a>(_arg: &Thing<'a>) -> &'a () { unimplemented!() } - | ~~~ + | ++ -error: aborting due to 3 previous errors +error[E0392]: parameter `'a` is never used + --> $DIR/return-without-lifetime.rs:2:12 + | +LL | struct Foo<'a>(&usize); + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0392. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr index 64d14d0fc5fa4..4d2460ef8de0c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -5,6 +5,11 @@ LL | let _: dyn Foo(&isize, &usize) -> &usize; | ------ ------ ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | let _: dyn for<'a> Foo(&isize, &usize) -> &'a usize; + | +++++++ ++ help: consider introducing a named lifetime parameter | LL ~ fn main<'a>() { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs index 37c87dbeaa9e5..e1deab736cf56 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs @@ -7,7 +7,6 @@ use std::fmt::Debug; struct Foo { x: Box, //~ ERROR missing lifetime specifier - //~^ ERROR E0228 } -fn main() { } +fn main() {} diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr index b865278e25fd8..fd08600280393 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr @@ -10,13 +10,6 @@ LL ~ struct Foo<'a> { LL ~ x: Box, | -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/dyn-trait-underscore-in-struct.rs:9:12 - | -LL | x: Box, - | ^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0106, E0228. -For more information about an error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr index 6a104e8f94b32..e9a1bf0fd999f 100644 --- a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr +++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr @@ -7,8 +7,8 @@ LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` help: consider introducing a named lifetime parameter | -LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } } - | ++++ ++ ++ ~~ +LL | fn foo<'a>(x: &u32, y: &u32) -> &'a u32 { loop { } } + | ++++ ~~ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.rs b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.rs index 3d049cc5639c0..1ea536dbfd6cf 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.rs +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.rs @@ -1,5 +1,6 @@ struct Foo<'a>(&'a u8); struct Baz<'a>(&'_ &'a u8); //~ ERROR missing lifetime specifier +//~^ ERROR in type `&'static &'a u8`, reference has a longer lifetime than the data it references fn foo<'_> //~ ERROR cannot be used here (_: Foo<'_>) {} diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index 22bf1fdba326f..006876efdf48f 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -1,15 +1,3 @@ -error[E0637]: `'_` cannot be used here - --> $DIR/underscore-lifetime-binders.rs:4:8 - | -LL | fn foo<'_> - | ^^ `'_` is a reserved lifetime name - -error[E0637]: `'_` cannot be used here - --> $DIR/underscore-lifetime-binders.rs:10:25 - | -LL | fn meh() -> Box Meh<'_>> - | ^^ `'_` is a reserved lifetime name - error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:2:17 | @@ -21,8 +9,20 @@ help: consider using the `'a` lifetime LL | struct Baz<'a>(&'a &'a u8); | ~~ +error[E0637]: `'_` cannot be used here + --> $DIR/underscore-lifetime-binders.rs:5:8 + | +LL | fn foo<'_> + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/underscore-lifetime-binders.rs:11:25 + | +LL | fn meh() -> Box Meh<'_>> + | ^^ `'_` is a reserved lifetime name + error[E0106]: missing lifetime specifier - --> $DIR/underscore-lifetime-binders.rs:10:33 + --> $DIR/underscore-lifetime-binders.rs:11:33 | LL | fn meh() -> Box Meh<'_>> | ^^ expected named lifetime parameter @@ -34,7 +34,7 @@ LL | fn meh() -> Box Meh<'static>> | ~~~~~~~ error[E0106]: missing lifetime specifier - --> $DIR/underscore-lifetime-binders.rs:16:35 + --> $DIR/underscore-lifetime-binders.rs:17:35 | LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } | ------ ------ ^^ expected named lifetime parameter @@ -42,10 +42,23 @@ LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y` help: consider introducing a named lifetime parameter | -LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y } - | ++++ ~~ ~~ ~~ +LL | fn foo2<'a>(_: &'_ u8, y: &'_ u8) -> &'a u8 { y } + | ++++ ~~ + +error[E0491]: in type `&'static &'a u8`, reference has a longer lifetime than the data it references + --> $DIR/underscore-lifetime-binders.rs:2:16 + | +LL | struct Baz<'a>(&'_ &'a u8); + | ^^^^^^^^^^ + | + = note: the pointer is valid for the static lifetime +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/underscore-lifetime-binders.rs:2:12 + | +LL | struct Baz<'a>(&'_ &'a u8); + | ^^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0106, E0637. +Some errors have detailed explanations: E0106, E0491, E0637. For more information about an error, try `rustc --explain E0106`. From f5ee6d2481d1793d65ecb832bd5205ba335cbdf6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 30 Apr 2022 10:39:15 +0200 Subject: [PATCH 10/11] Remove spurious change. --- src/test/ui/abi/numbers-arithmetic/i128-ffi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs b/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs index b119e46d7cdba..19edf9779f35e 100644 --- a/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs +++ b/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs @@ -12,7 +12,7 @@ extern "C" { fn identity(f: u128) -> u128; fn square(f: i128) -> i128; - fn sub(f: i128, g: i128) -> i128; + fn sub(f: i128, f: i128) -> i128; } fn main() { From 2bf9e1e19b8f86647329d9d868fbe317eee63094 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 30 Apr 2022 10:43:24 +0200 Subject: [PATCH 11/11] Ignore tidy --- compiler/rustc_resolve/src/late.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5089a53315765..d5603fac4af03 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength +// FIXME(cjgillot) Separate name and lifetime resolution since they use separate namespaces. //! "Late resolution" is the pass that resolves most of names in a crate beside imports and macros. //! It runs when the crate is fully expanded and its module structure is fully built. //! So it just walks through the crate and resolves all the expressions, types, etc.