Skip to content

Commit 130a9d0

Browse files
Resolve elided lifetimes in assoc const to static if no other lifetimes are in scope
1 parent c00957a commit 130a9d0

File tree

8 files changed

+91
-115
lines changed

8 files changed

+91
-115
lines changed

compiler/rustc_lint/src/context/diagnostics.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -333,13 +333,17 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
333333
Applicability::MachineApplicable,
334334
);
335335
}
336-
BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span } => {
336+
BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span, lifetimes_in_scope } => {
337337
diag.span_suggestion_verbose(
338338
if elided { span.shrink_to_hi() } else { span },
339339
"use the `'static` lifetime",
340340
if elided { "'static " } else { "'static" },
341341
Applicability::MachineApplicable,
342342
);
343+
diag.span_note(
344+
lifetimes_in_scope,
345+
"cannot automatically infer `'static` because of other lifetimes in scope",
346+
);
343347
}
344348
BuiltinLintDiag::RedundantImportVisibility { max_vis, span } => {
345349
diag.span_note(span, format!("the most public imported item is `{max_vis}`"));

compiler/rustc_lint_defs/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ pub enum BuiltinLintDiag {
658658
AssociatedConstElidedLifetime {
659659
elided: bool,
660660
span: Span,
661+
lifetimes_in_scope: MultiSpan,
661662
},
662663
RedundantImportVisibility {
663664
span: Span,

compiler/rustc_resolve/src/late.rs

+69-45
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,10 @@ enum LifetimeRibKind {
310310
/// error on default object bounds (e.g., `Box<dyn Foo>`).
311311
AnonymousReportError,
312312

313-
/// Resolves elided lifetimes to `'static`, but gives a warning that this behavior
314-
/// is a bug and will be reverted soon.
315-
AnonymousWarn(NodeId),
313+
/// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope,
314+
/// otherwise give a warning that the previous behavior of introducing a new early-bound
315+
/// lifetime is a bug and will be removed.
316+
StaticIfNoLifetimeInScope(NodeId),
316317

317318
/// Signal we cannot find which should be the anonymous lifetime.
318319
ElisionFailure,
@@ -1209,7 +1210,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
12091210
}
12101211
LifetimeRibKind::AnonymousCreateParameter { .. }
12111212
| LifetimeRibKind::AnonymousReportError
1212-
| LifetimeRibKind::AnonymousWarn(_)
1213+
| LifetimeRibKind::StaticIfNoLifetimeInScope(_)
12131214
| LifetimeRibKind::Elided(_)
12141215
| LifetimeRibKind::ElisionFailure
12151216
| LifetimeRibKind::ConcreteAnonConst(_)
@@ -1577,7 +1578,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
15771578
// lifetime would be illegal.
15781579
LifetimeRibKind::Item
15791580
| LifetimeRibKind::AnonymousReportError
1580-
| LifetimeRibKind::AnonymousWarn(_)
1581+
| LifetimeRibKind::StaticIfNoLifetimeInScope(_)
15811582
| LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
15821583
// An anonymous lifetime is legal here, and bound to the right
15831584
// place, go ahead.
@@ -1640,7 +1641,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
16401641
| LifetimeRibKind::Generics { .. }
16411642
| LifetimeRibKind::ElisionFailure
16421643
| LifetimeRibKind::AnonymousReportError
1643-
| LifetimeRibKind::AnonymousWarn(_) => {}
1644+
| LifetimeRibKind::StaticIfNoLifetimeInScope(_) => {}
16441645
}
16451646
}
16461647

@@ -1674,22 +1675,42 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
16741675
self.record_lifetime_res(lifetime.id, res, elision_candidate);
16751676
return;
16761677
}
1677-
LifetimeRibKind::AnonymousWarn(node_id) => {
1678-
let msg = if elided {
1679-
"`&` without an explicit lifetime name cannot be used here"
1678+
LifetimeRibKind::StaticIfNoLifetimeInScope(node_id) => {
1679+
let mut lifetimes_in_scope = vec![];
1680+
for rib in &self.lifetime_ribs[..i] {
1681+
lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span));
1682+
// Consider any anonymous lifetimes, too
1683+
if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind
1684+
&& let Some(extra) = self.r.extra_lifetime_params_map.get(&binder)
1685+
{
1686+
lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span));
1687+
}
1688+
}
1689+
if lifetimes_in_scope.is_empty() {
1690+
self.record_lifetime_res(
1691+
lifetime.id,
1692+
LifetimeRes::Static,
1693+
elision_candidate,
1694+
);
1695+
return;
16801696
} else {
1681-
"`'_` cannot be used here"
1682-
};
1683-
self.r.lint_buffer.buffer_lint_with_diagnostic(
1684-
lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
1685-
node_id,
1686-
lifetime.ident.span,
1687-
msg,
1688-
lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
1689-
elided,
1690-
span: lifetime.ident.span,
1691-
},
1692-
);
1697+
let msg = if elided {
1698+
"`&` without an explicit lifetime name cannot be used here"
1699+
} else {
1700+
"`'_` cannot be used here"
1701+
};
1702+
self.r.lint_buffer.buffer_lint_with_diagnostic(
1703+
lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
1704+
node_id,
1705+
lifetime.ident.span,
1706+
msg,
1707+
lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
1708+
elided,
1709+
span: lifetime.ident.span,
1710+
lifetimes_in_scope: lifetimes_in_scope.into(),
1711+
},
1712+
);
1713+
}
16931714
}
16941715
LifetimeRibKind::AnonymousReportError => {
16951716
if elided {
@@ -1882,7 +1903,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
18821903
// impl Foo for std::cell::Ref<u32> // note lack of '_
18831904
// async fn foo(_: std::cell::Ref<u32>) { ... }
18841905
LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
1885-
| LifetimeRibKind::AnonymousWarn(_) => {
1906+
| LifetimeRibKind::StaticIfNoLifetimeInScope(_) => {
18861907
let sess = self.r.tcx.sess;
18871908
let subdiag = rustc_errors::elided_lifetime_in_path_suggestion(
18881909
sess.source_map(),
@@ -3009,30 +3030,33 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
30093030
kind: LifetimeBinderKind::ConstItem,
30103031
},
30113032
|this| {
3012-
this.with_lifetime_rib(LifetimeRibKind::AnonymousWarn(item.id), |this| {
3013-
// If this is a trait impl, ensure the const
3014-
// exists in trait
3015-
this.check_trait_item(
3016-
item.id,
3017-
item.ident,
3018-
&item.kind,
3019-
ValueNS,
3020-
item.span,
3021-
seen_trait_items,
3022-
|i, s, c| ConstNotMemberOfTrait(i, s, c),
3023-
);
3033+
this.with_lifetime_rib(
3034+
LifetimeRibKind::StaticIfNoLifetimeInScope(item.id),
3035+
|this| {
3036+
// If this is a trait impl, ensure the const
3037+
// exists in trait
3038+
this.check_trait_item(
3039+
item.id,
3040+
item.ident,
3041+
&item.kind,
3042+
ValueNS,
3043+
item.span,
3044+
seen_trait_items,
3045+
|i, s, c| ConstNotMemberOfTrait(i, s, c),
3046+
);
30243047

3025-
this.visit_generics(generics);
3026-
this.visit_ty(ty);
3027-
if let Some(expr) = expr {
3028-
// We allow arbitrary const expressions inside of associated consts,
3029-
// even if they are potentially not const evaluatable.
3030-
//
3031-
// Type parameters can already be used and as associated consts are
3032-
// not used as part of the type system, this is far less surprising.
3033-
this.resolve_const_body(expr, None);
3034-
}
3035-
});
3048+
this.visit_generics(generics);
3049+
this.visit_ty(ty);
3050+
if let Some(expr) = expr {
3051+
// We allow arbitrary const expressions inside of associated consts,
3052+
// even if they are potentially not const evaluatable.
3053+
//
3054+
// Type parameters can already be used and as associated consts are
3055+
// not used as part of the type system, this is far less surprising.
3056+
this.resolve_const_body(expr, None);
3057+
}
3058+
},
3059+
);
30363060
},
30373061
);
30383062
}
+3-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1+
//@ check-pass
2+
13
struct S;
24

35
impl S {
46
const C: &&str = &"";
5-
//~^ WARN `&` without an explicit lifetime name cannot be used here
6-
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
7-
//~| WARN `&` without an explicit lifetime name cannot be used here
8-
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
9-
//~| ERROR in type `&&str`, reference has a longer lifetime than the data it references
7+
// Now resolves to `&'static &'static str`.
108
}
119

1210
fn main() {}

tests/ui/associated-consts/double-elided.stderr

-47
This file was deleted.

tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs

-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ trait Trait {
55
impl Trait for () {
66
const ASSOC: &dyn Fn(_) = 1i32;
77
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated constants
8-
//~| WARN `&` without an explicit lifetime name cannot be used here
9-
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
108
}
119

1210
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,9 @@
1-
warning: `&` without an explicit lifetime name cannot be used here
2-
--> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:18
3-
|
4-
LL | const ASSOC: &dyn Fn(_) = 1i32;
5-
| ^
6-
|
7-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8-
= note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
9-
= note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default
10-
help: use the `'static` lifetime
11-
|
12-
LL | const ASSOC: &'static dyn Fn(_) = 1i32;
13-
| +++++++
14-
151
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
162
--> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:26
173
|
184
LL | const ASSOC: &dyn Fn(_) = 1i32;
195
| ^ not allowed in type signatures
206

21-
error: aborting due to 1 previous error; 1 warning emitted
7+
error: aborting due to 1 previous error
228

239
For more information about this error, try `rustc --explain E0121`.

tests/ui/consts/assoc-const-elided-lifetime.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&()> };
66
|
77
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
88
= note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
9+
note: cannot automatically infer `'static` because of other lifetimes in scope
10+
--> $DIR/assoc-const-elided-lifetime.rs:9:6
11+
|
12+
LL | impl<'a> Foo<'a> {
13+
| ^^
914
note: the lint level is defined here
1015
--> $DIR/assoc-const-elided-lifetime.rs:1:9
1116
|
@@ -24,6 +29,13 @@ LL | const BAR: &() = &();
2429
|
2530
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
2631
= note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
32+
note: cannot automatically infer `'static` because of other lifetimes in scope
33+
--> $DIR/assoc-const-elided-lifetime.rs:9:6
34+
|
35+
LL | impl<'a> Foo<'a> {
36+
| ^^
37+
LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&()> };
38+
| ^^
2739
help: use the `'static` lifetime
2840
|
2941
LL | const BAR: &'static () = &();

0 commit comments

Comments
 (0)