about summary refs log tree commit diff
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2024-06-17 04:53:54 +0100
committerGitHub <noreply@github.com>2024-06-17 04:53:54 +0100
commit23b936f98185b39ce2cf00eaf85be574196df4c8 (patch)
tree2a2104e107d65a79f2ce8ac396042dd3aa6e9b3b
parent6b65c30f8e0f6c18aa5f32cbad869b1d036c7851 (diff)
parent5f3357c3c68e555c655c71bb8672db7908622c5b (diff)
downloadrust-23b936f98185b39ce2cf00eaf85be574196df4c8.tar.gz
rust-23b936f98185b39ce2cf00eaf85be574196df4c8.zip
Rollup merge of #125258 - compiler-errors:static-if-no-lt, r=nnethercote
Resolve elided lifetimes in assoc const to static if no other lifetimes are in scope

Implements the change to elided lifetime resolution in *associated consts* subject to FCP here: https://github.com/rust-lang/rust/issues/125190#issue-2301532282

Specifically, walk the enclosing lifetime ribs in an associated const, and if we find no other lifetimes, then resolve to `'static`.

Also make it work for traits, but don't lint -- just give a hard error in that case.
-rw-r--r--compiler/rustc_lint/messages.ftl1
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs15
-rw-r--r--compiler/rustc_lint/src/lints.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs8
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs1
-rw-r--r--compiler/rustc_resolve/src/late.rs142
-rw-r--r--tests/ui/associated-consts/double-elided.rs8
-rw-r--r--tests/ui/associated-consts/double-elided.stderr47
-rw-r--r--tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs2
-rw-r--r--tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr16
-rw-r--r--tests/ui/consts/assoc-const-elided-lifetime.stderr12
-rw-r--r--tests/ui/consts/static-default-lifetime/elided-lifetime.rs22
-rw-r--r--tests/ui/consts/static-default-lifetime/elided-lifetime.stderr59
-rw-r--r--tests/ui/consts/static-default-lifetime/generic-associated-const.rs19
-rw-r--r--tests/ui/consts/static-default-lifetime/generic-associated-const.stderr46
-rw-r--r--tests/ui/consts/static-default-lifetime/inner-item.rs21
-rw-r--r--tests/ui/consts/static-default-lifetime/static-trait-impl.rs20
-rw-r--r--tests/ui/consts/static-default-lifetime/static-trait-impl.stderr45
-rw-r--r--tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr56
-rw-r--r--tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr46
-rw-r--r--tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs8
21 files changed, 386 insertions, 210 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 043042a492b..da1f36112ab 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -14,6 +14,7 @@ lint_associated_const_elided_lifetime = {$elided ->
         *[false] `'_` cannot be used here
     }
     .suggestion = use the `'static` lifetime
+    .note = cannot automatically infer `'static` because of other lifetimes in scope
 
 lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
     .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 83640d7210f..290bb5173db 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -319,11 +319,20 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
         BuiltinLintDiag::UnusedQualifications { removal_span } => {
             lints::UnusedQualifications { removal_span }.decorate_lint(diag);
         }
-        BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span } => {
+        BuiltinLintDiag::AssociatedConstElidedLifetime {
+            elided,
+            span: lt_span,
+            lifetimes_in_scope,
+        } => {
             let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span };
             let code = if elided { "'static " } else { "'static" };
-            lints::AssociatedConstElidedLifetime { span: lt_span, code, elided }
-                .decorate_lint(diag);
+            lints::AssociatedConstElidedLifetime {
+                span: lt_span,
+                code,
+                elided,
+                lifetimes_in_scope,
+            }
+            .decorate_lint(diag);
         }
         BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => {
             lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis }
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 8059f5c1a2e..f60f8f7c6b7 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2873,6 +2873,8 @@ pub struct AssociatedConstElidedLifetime {
 
     pub code: &'static str,
     pub elided: bool,
+    #[note]
+    pub lifetimes_in_scope: MultiSpan,
 }
 
 #[derive(LintDiagnostic)]
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index a12c76037e7..1913b9d6a1c 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4593,16 +4593,18 @@ declare_lint! {
 
 declare_lint! {
     /// The `elided_lifetimes_in_associated_constant` lint detects elided lifetimes
-    /// that were erroneously allowed in associated constants.
+    /// in associated constants when there are other lifetimes in scope. This was
+    /// accidentally supported, and this lint was later relaxed to allow eliding
+    /// lifetimes to `'static` when there are no lifetimes in scope.
     ///
     /// ### Example
     ///
     /// ```rust,compile_fail
     /// #![deny(elided_lifetimes_in_associated_constant)]
     ///
-    /// struct Foo;
+    /// struct Foo<'a>(&'a ());
     ///
-    /// impl Foo {
+    /// impl<'a> Foo<'a> {
     ///     const STR: &str = "hello, world";
     /// }
     /// ```
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 1ce95df3404..70330c44577 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -696,6 +696,7 @@ pub enum BuiltinLintDiag {
     AssociatedConstElidedLifetime {
         elided: bool,
         span: Span,
+        lifetimes_in_scope: MultiSpan,
     },
     RedundantImportVisibility {
         span: Span,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index fa711d932b6..c1e83c59f98 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -310,9 +310,10 @@ enum LifetimeRibKind {
     /// error on default object bounds (e.g., `Box<dyn Foo>`).
     AnonymousReportError,
 
-    /// Resolves elided lifetimes to `'static`, but gives a warning that this behavior
-    /// is a bug and will be reverted soon.
-    AnonymousWarn(NodeId),
+    /// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope,
+    /// otherwise give a warning that the previous behavior of introducing a new early-bound
+    /// lifetime is a bug and will be removed (if `emit_lint` is enabled).
+    StaticIfNoLifetimeInScope { lint_id: NodeId, emit_lint: bool },
 
     /// Signal we cannot find which should be the anonymous lifetime.
     ElisionFailure,
@@ -1212,7 +1213,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                             }
                             LifetimeRibKind::AnonymousCreateParameter { .. }
                             | LifetimeRibKind::AnonymousReportError
-                            | LifetimeRibKind::AnonymousWarn(_)
+                            | LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
                             | LifetimeRibKind::Elided(_)
                             | LifetimeRibKind::ElisionFailure
                             | LifetimeRibKind::ConcreteAnonConst(_)
@@ -1580,7 +1581,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                                     // lifetime would be illegal.
                                     LifetimeRibKind::Item
                                     | LifetimeRibKind::AnonymousReportError
-                                    | LifetimeRibKind::AnonymousWarn(_)
+                                    | LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
                                     | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
                                     // An anonymous lifetime is legal here, and bound to the right
                                     // place, go ahead.
@@ -1643,7 +1644,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 | LifetimeRibKind::Generics { .. }
                 | LifetimeRibKind::ElisionFailure
                 | LifetimeRibKind::AnonymousReportError
-                | LifetimeRibKind::AnonymousWarn(_) => {}
+                | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {}
             }
         }
 
@@ -1677,16 +1678,36 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     self.record_lifetime_res(lifetime.id, res, elision_candidate);
                     return;
                 }
-                LifetimeRibKind::AnonymousWarn(node_id) => {
-                    self.r.lint_buffer.buffer_lint(
-                        lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
-                        node_id,
-                        lifetime.ident.span,
-                        lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
-                            elided,
-                            span: lifetime.ident.span,
-                        },
-                    );
+                LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => {
+                    let mut lifetimes_in_scope = vec![];
+                    for rib in &self.lifetime_ribs[..i] {
+                        lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span));
+                        // Consider any anonymous lifetimes, too
+                        if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind
+                            && let Some(extra) = self.r.extra_lifetime_params_map.get(&binder)
+                        {
+                            lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span));
+                        }
+                    }
+                    if lifetimes_in_scope.is_empty() {
+                        self.record_lifetime_res(
+                            lifetime.id,
+                            LifetimeRes::Static,
+                            elision_candidate,
+                        );
+                        return;
+                    } else if emit_lint {
+                        self.r.lint_buffer.buffer_lint(
+                            lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
+                            node_id,
+                            lifetime.ident.span,
+                            lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
+                                elided,
+                                span: lifetime.ident.span,
+                                lifetimes_in_scope: lifetimes_in_scope.into(),
+                            },
+                        );
+                    }
                 }
                 LifetimeRibKind::AnonymousReportError => {
                     if elided {
@@ -1904,7 +1925,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     //     impl Foo for std::cell::Ref<u32> // note lack of '_
                     //     async fn foo(_: std::cell::Ref<u32>) { ... }
                     LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
-                    | LifetimeRibKind::AnonymousWarn(_) => {
+                    | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {
                         let sess = self.r.tcx.sess;
                         let subdiag = rustc_errors::elided_lifetime_in_path_suggestion(
                             sess.source_map(),
@@ -2838,19 +2859,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                             kind: LifetimeBinderKind::ConstItem,
                         },
                         |this| {
-                            this.visit_generics(generics);
-                            this.visit_ty(ty);
-
-                            // Only impose the restrictions of `ConstRibKind` for an
-                            // actual constant expression in a provided default.
-                            if let Some(expr) = expr {
-                                // 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.resolve_const_body(expr, None);
-                            }
+                            this.with_lifetime_rib(
+                                LifetimeRibKind::StaticIfNoLifetimeInScope {
+                                    lint_id: item.id,
+                                    emit_lint: false,
+                                },
+                                |this| {
+                                    this.visit_generics(generics);
+                                    this.visit_ty(ty);
+
+                                    // Only impose the restrictions of `ConstRibKind` for an
+                                    // actual constant expression in a provided default.
+                                    if let Some(expr) = expr {
+                                        // 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.resolve_const_body(expr, None);
+                                    }
+                                },
+                            )
                         },
                     );
                 }
@@ -3030,30 +3059,37 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                         kind: LifetimeBinderKind::ConstItem,
                     },
                     |this| {
-                        this.with_lifetime_rib(LifetimeRibKind::AnonymousWarn(item.id), |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,
-                                seen_trait_items,
-                                |i, s, c| ConstNotMemberOfTrait(i, s, c),
-                            );
+                        this.with_lifetime_rib(
+                            LifetimeRibKind::StaticIfNoLifetimeInScope {
+                                lint_id: item.id,
+                                // In impls, it's not a hard error yet due to backcompat.
+                                emit_lint: true,
+                            },
+                            |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,
+                                    seen_trait_items,
+                                    |i, s, c| ConstNotMemberOfTrait(i, s, c),
+                                );
 
-                            this.visit_generics(generics);
-                            this.visit_ty(ty);
-                            if let Some(expr) = expr {
-                                // 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.resolve_const_body(expr, None);
-                            }
-                        });
+                                this.visit_generics(generics);
+                                this.visit_ty(ty);
+                                if let Some(expr) = expr {
+                                    // 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.resolve_const_body(expr, None);
+                                }
+                            },
+                        );
                     },
                 );
             }
diff --git a/tests/ui/associated-consts/double-elided.rs b/tests/ui/associated-consts/double-elided.rs
index fd0317781bb..6831b599374 100644
--- a/tests/ui/associated-consts/double-elided.rs
+++ b/tests/ui/associated-consts/double-elided.rs
@@ -1,12 +1,10 @@
+//@ check-pass
+
 struct S;
 
 impl S {
     const C: &&str = &"";
-    //~^ WARN `&` without an explicit lifetime name cannot be used here
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| WARN `&` without an explicit lifetime name cannot be used here
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| ERROR in type `&&str`, reference has a longer lifetime than the data it references
+    // Now resolves to `&'static &'static str`.
 }
 
 fn main() {}
diff --git a/tests/ui/associated-consts/double-elided.stderr b/tests/ui/associated-consts/double-elided.stderr
deleted file mode 100644
index 67834788ccd..00000000000
--- a/tests/ui/associated-consts/double-elided.stderr
+++ /dev/null
@@ -1,47 +0,0 @@
-warning: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/double-elided.rs:4:14
-   |
-LL |     const C: &&str = &"";
-   |              ^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
-   = note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default
-help: use the `'static` lifetime
-   |
-LL |     const C: &'static &str = &"";
-   |               +++++++
-
-warning: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/double-elided.rs:4:15
-   |
-LL |     const C: &&str = &"";
-   |               ^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
-help: use the `'static` lifetime
-   |
-LL |     const C: &&'static str = &"";
-   |                +++++++
-
-error[E0491]: in type `&&str`, reference has a longer lifetime than the data it references
-  --> $DIR/double-elided.rs:4:5
-   |
-LL |     const C: &&str = &"";
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the pointer is valid for the anonymous lifetime as defined here
-  --> $DIR/double-elided.rs:4:14
-   |
-LL |     const C: &&str = &"";
-   |              ^
-note: but the referenced data is only valid for the anonymous lifetime as defined here
-  --> $DIR/double-elided.rs:4:14
-   |
-LL |     const C: &&str = &"";
-   |              ^
-
-error: aborting due to 1 previous error; 2 warnings emitted
-
-For more information about this error, try `rustc --explain E0491`.
diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs
index 1e0b77b0d3b..40896c32e11 100644
--- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs
+++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs
@@ -5,8 +5,6 @@ trait Trait {
 impl Trait for () {
     const ASSOC: &dyn Fn(_) = 1i32;
     //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated constants
-    //~| WARN `&` without an explicit lifetime name cannot be used here
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
 
 fn main() {}
diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr
index e946491a084..6b8ba9af7a0 100644
--- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr
+++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr
@@ -1,23 +1,9 @@
-warning: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:18
-   |
-LL |     const ASSOC: &dyn Fn(_) = 1i32;
-   |                  ^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
-   = note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default
-help: use the `'static` lifetime
-   |
-LL |     const ASSOC: &'static dyn Fn(_) = 1i32;
-   |                   +++++++
-
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
   --> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:26
    |
 LL |     const ASSOC: &dyn Fn(_) = 1i32;
    |                          ^ not allowed in type signatures
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/consts/assoc-const-elided-lifetime.stderr b/tests/ui/consts/assoc-const-elided-lifetime.stderr
index a1eeaff4ba8..3e847298c35 100644
--- a/tests/ui/consts/assoc-const-elided-lifetime.stderr
+++ b/tests/ui/consts/assoc-const-elided-lifetime.stderr
@@ -6,6 +6,11 @@ LL |     const FOO: Foo<'_> = Foo { x: PhantomData::<&()> };
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+note: cannot automatically infer `'static` because of other lifetimes in scope
+  --> $DIR/assoc-const-elided-lifetime.rs:9:6
+   |
+LL | impl<'a> Foo<'a> {
+   |      ^^
 note: the lint level is defined here
   --> $DIR/assoc-const-elided-lifetime.rs:1:9
    |
@@ -24,6 +29,13 @@ LL |     const BAR: &() = &();
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+note: cannot automatically infer `'static` because of other lifetimes in scope
+  --> $DIR/assoc-const-elided-lifetime.rs:9:6
+   |
+LL | impl<'a> Foo<'a> {
+   |      ^^
+LL |     const FOO: Foo<'_> = Foo { x: PhantomData::<&()> };
+   |                    ^^
 help: use the `'static` lifetime
    |
 LL |     const BAR: &'static () = &();
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
new file mode 100644
index 00000000000..95d59f9b894
--- /dev/null
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
@@ -0,0 +1,22 @@
+#![deny(elided_lifetimes_in_associated_constant)]
+
+struct Foo<'a>(&'a ());
+
+impl Foo<'_> {
+    const STATIC: &str = "";
+    //~^ ERROR `&` without an explicit lifetime name cannot be used here
+    //~| WARN this was previously accepted by the compiler but is being phased out
+}
+
+trait Bar {
+    const STATIC: &str;
+}
+
+impl Bar for Foo<'_> {
+    const STATIC: &str = "";
+    //~^ ERROR `&` without an explicit lifetime name cannot be used here
+    //~| WARN this was previously accepted by the compiler but is being phased out
+    //~| ERROR const not compatible with trait
+}
+
+fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
new file mode 100644
index 00000000000..d4fc1717538
--- /dev/null
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
@@ -0,0 +1,59 @@
+error: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/elided-lifetime.rs:6:19
+   |
+LL |     const STATIC: &str = "";
+   |                   ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+note: cannot automatically infer `'static` because of other lifetimes in scope
+  --> $DIR/elided-lifetime.rs:5:10
+   |
+LL | impl Foo<'_> {
+   |          ^^
+note: the lint level is defined here
+  --> $DIR/elided-lifetime.rs:1:9
+   |
+LL | #![deny(elided_lifetimes_in_associated_constant)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use the `'static` lifetime
+   |
+LL |     const STATIC: &'static str = "";
+   |                    +++++++
+
+error: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/elided-lifetime.rs:16:19
+   |
+LL |     const STATIC: &str = "";
+   |                   ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+note: cannot automatically infer `'static` because of other lifetimes in scope
+  --> $DIR/elided-lifetime.rs:15:18
+   |
+LL | impl Bar for Foo<'_> {
+   |                  ^^
+help: use the `'static` lifetime
+   |
+LL |     const STATIC: &'static str = "";
+   |                    +++++++
+
+error[E0308]: const not compatible with trait
+  --> $DIR/elided-lifetime.rs:16:5
+   |
+LL |     const STATIC: &str = "";
+   |     ^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected reference `&'static _`
+              found reference `&_`
+note: the anonymous lifetime as defined here...
+  --> $DIR/elided-lifetime.rs:15:18
+   |
+LL | impl Bar for Foo<'_> {
+   |                  ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/static-default-lifetime/generic-associated-const.rs b/tests/ui/consts/static-default-lifetime/generic-associated-const.rs
new file mode 100644
index 00000000000..721920bd810
--- /dev/null
+++ b/tests/ui/consts/static-default-lifetime/generic-associated-const.rs
@@ -0,0 +1,19 @@
+#![deny(elided_lifetimes_in_associated_constant)]
+#![feature(generic_const_items)]
+//~^ WARN the feature `generic_const_items` is incomplete
+
+struct A;
+impl A {
+    const GAC_TYPE<T>: &str = "";
+    const GAC_LIFETIME<'a>: &str = "";
+    //~^ ERROR `&` without an explicit lifetime name cannot be used here
+    //~| WARN this was previously accepted by the compiler but is being phased out
+}
+
+trait Trait {
+    const GAC_TYPE<T>: &str = "";
+    const GAC_LIFETIME<'a>: &str = "";
+    //~^ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr b/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr
new file mode 100644
index 00000000000..2ecab3442a9
--- /dev/null
+++ b/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr
@@ -0,0 +1,46 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/generic-associated-const.rs:15:29
+   |
+LL |     const GAC_LIFETIME<'a>: &str = "";
+   |                             ^ expected named lifetime parameter
+   |
+help: consider using the `'a` lifetime
+   |
+LL |     const GAC_LIFETIME<'a>: &'a str = "";
+   |                              ++
+
+warning: the feature `generic_const_items` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/generic-associated-const.rs:2:12
+   |
+LL | #![feature(generic_const_items)]
+   |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/generic-associated-const.rs:8:29
+   |
+LL |     const GAC_LIFETIME<'a>: &str = "";
+   |                             ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+note: cannot automatically infer `'static` because of other lifetimes in scope
+  --> $DIR/generic-associated-const.rs:8:24
+   |
+LL |     const GAC_LIFETIME<'a>: &str = "";
+   |                        ^^
+note: the lint level is defined here
+  --> $DIR/generic-associated-const.rs:1:9
+   |
+LL | #![deny(elided_lifetimes_in_associated_constant)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use the `'static` lifetime
+   |
+LL |     const GAC_LIFETIME<'a>: &'static str = "";
+   |                              +++++++
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/consts/static-default-lifetime/inner-item.rs b/tests/ui/consts/static-default-lifetime/inner-item.rs
new file mode 100644
index 00000000000..061b240a40d
--- /dev/null
+++ b/tests/ui/consts/static-default-lifetime/inner-item.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+
+struct Foo<'a>(&'a ());
+
+impl<'a> Foo<'a> {
+    fn hello(self) {
+        const INNER: &str = "";
+    }
+}
+
+impl Foo<'_> {
+    fn implicit(self) {
+        const INNER: &str = "";
+    }
+
+    fn fn_lifetime(&self) {
+        const INNER: &str = "";
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
new file mode 100644
index 00000000000..025fda4df58
--- /dev/null
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
@@ -0,0 +1,20 @@
+#![deny(elided_lifetimes_in_associated_constant)]
+
+trait Bar<'a> {
+    const STATIC: &'a str;
+}
+
+struct A;
+impl Bar<'_> for A {
+    const STATIC: &str = "";
+    //~^ ERROR `&` without an explicit lifetime name cannot be used here
+    //~| WARN this was previously accepted by the compiler but is being phased out
+    //~| ERROR const not compatible with trait
+}
+
+struct B;
+impl Bar<'static> for B {
+    const STATIC: &str = "";
+}
+
+fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
new file mode 100644
index 00000000000..8e4c27875ab
--- /dev/null
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
@@ -0,0 +1,45 @@
+error: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/static-trait-impl.rs:9:19
+   |
+LL |     const STATIC: &str = "";
+   |                   ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+note: cannot automatically infer `'static` because of other lifetimes in scope
+  --> $DIR/static-trait-impl.rs:8:10
+   |
+LL | impl Bar<'_> for A {
+   |          ^^
+note: the lint level is defined here
+  --> $DIR/static-trait-impl.rs:1:9
+   |
+LL | #![deny(elided_lifetimes_in_associated_constant)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use the `'static` lifetime
+   |
+LL |     const STATIC: &'static str = "";
+   |                    +++++++
+
+error[E0308]: const not compatible with trait
+  --> $DIR/static-trait-impl.rs:9:5
+   |
+LL |     const STATIC: &str = "";
+   |     ^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected reference `&_`
+              found reference `&_`
+note: the anonymous lifetime as defined here...
+  --> $DIR/static-trait-impl.rs:8:10
+   |
+LL | impl Bar<'_> for A {
+   |          ^^
+note: ...does not necessarily outlive the anonymous lifetime as defined here
+  --> $DIR/static-trait-impl.rs:8:10
+   |
+LL | impl Bar<'_> for A {
+   |          ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr
index 24e2e0a0f7a..71ac55bf044 100644
--- a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr
+++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.default.stderr
@@ -1,57 +1,25 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-in-assoc-const-type.rs:6:14
-   |
-LL |     const A: &str = "";
-   |              ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL ~ trait ZstAssert<'a>: Sized {
-LL ~     const A: &'a str = "";
-   |
-
-error[E0106]: missing lifetime specifier
+error[E0726]: implicit elided lifetime not allowed here
   --> $DIR/missing-lifetime-in-assoc-const-type.rs:7:14
    |
 LL |     const B: S = S { s: &() };
-   |              ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL ~ trait ZstAssert<'a>: Sized {
-LL |     const A: &str = "";
-LL ~     const B: S<'a> = S { s: &() };
+   |              ^ expected lifetime parameter
    |
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-in-assoc-const-type.rs:8:15
-   |
-LL |     const C: &'_ str = "";
-   |               ^^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL ~ trait ZstAssert<'a>: Sized {
-LL |     const A: &str = "";
-LL |     const B: S = S { s: &() };
-LL ~     const C: &'a str = "";
+help: indicate the anonymous lifetime
    |
+LL |     const B: S<'_> = S { s: &() };
+   |               ++++
 
-error[E0106]: missing lifetime specifiers
+error[E0726]: implicit elided lifetime not allowed here
   --> $DIR/missing-lifetime-in-assoc-const-type.rs:9:14
    |
 LL |     const D: T = T { a: &(), b: &() };
-   |              ^ expected 2 lifetime parameters
-   |
-help: consider introducing a named lifetime parameter
+   |              ^ expected lifetime parameters
    |
-LL ~ trait ZstAssert<'a>: Sized {
-LL |     const A: &str = "";
-LL |     const B: S = S { s: &() };
-LL |     const C: &'_ str = "";
-LL ~     const D: T<'a, 'a> = T { a: &(), b: &() };
+help: indicate the anonymous lifetimes
    |
+LL |     const D: T<'_, '_> = T { a: &(), b: &() };
+   |               ++++++++
 
-error: aborting due to 4 previous errors
+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 E0726`.
diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr
index a97ffe7da79..71ac55bf044 100644
--- a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr
+++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.generic_const_items.stderr
@@ -1,47 +1,25 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-in-assoc-const-type.rs:6:14
-   |
-LL |     const A: &str = "";
-   |              ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     const A<'a>: &'a str = "";
-   |            ++++   ++
-
-error[E0106]: missing lifetime specifier
+error[E0726]: implicit elided lifetime not allowed here
   --> $DIR/missing-lifetime-in-assoc-const-type.rs:7:14
    |
 LL |     const B: S = S { s: &() };
-   |              ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     const B<'a>: S<'a> = S { s: &() };
-   |            ++++   ++++
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-in-assoc-const-type.rs:8:15
-   |
-LL |     const C: &'_ str = "";
-   |               ^^ expected named lifetime parameter
+   |              ^ expected lifetime parameter
    |
-help: consider introducing a named lifetime parameter
+help: indicate the anonymous lifetime
    |
-LL |     const C<'a>: &'a str = "";
-   |            ++++   ~~
+LL |     const B: S<'_> = S { s: &() };
+   |               ++++
 
-error[E0106]: missing lifetime specifiers
+error[E0726]: implicit elided lifetime not allowed here
   --> $DIR/missing-lifetime-in-assoc-const-type.rs:9:14
    |
 LL |     const D: T = T { a: &(), b: &() };
-   |              ^ expected 2 lifetime parameters
+   |              ^ expected lifetime parameters
    |
-help: consider introducing a named lifetime parameter
+help: indicate the anonymous lifetimes
    |
-LL |     const D<'a>: T<'a, 'a> = T { a: &(), b: &() };
-   |            ++++   ++++++++
+LL |     const D: T<'_, '_> = T { a: &(), b: &() };
+   |               ++++++++
 
-error: aborting due to 4 previous errors
+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 E0726`.
diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs
index f36a6567e42..a60f0b94587 100644
--- a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs
+++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs
@@ -3,10 +3,10 @@
 #![cfg_attr(generic_const_items, feature(generic_const_items), allow(incomplete_features))]
 
 trait ZstAssert: Sized {
-    const A: &str = ""; //~ ERROR missing lifetime specifier
-    const B: S = S { s: &() }; //~ ERROR missing lifetime specifier
-    const C: &'_ str = ""; //~ ERROR missing lifetime specifier
-    const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier
+    const A: &str = "";
+    const B: S = S { s: &() }; //~ ERROR implicit elided lifetime not allowed here
+    const C: &'_ str = "";
+    const D: T = T { a: &(), b: &() }; //~ ERROR implicit elided lifetime not allowed here
 }
 
 struct S<'a> {