Skip to content

Commit c00f635

Browse files
Remove in-band lifetimes
1 parent 3b18651 commit c00f635

File tree

66 files changed

+57
-1458
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+57
-1458
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+12-45
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,9 @@ struct LoweringContext<'a, 'hir: 'a> {
141141
/// indicate whether or not we're in a place where new lifetimes will result
142142
/// in in-band lifetime definitions, such a function or an impl header,
143143
/// including implicit lifetimes from `impl_header_lifetime_elision`.
144-
is_collecting_in_band_lifetimes: bool,
144+
is_collecting_anonymous_lifetimes: bool,
145145

146146
/// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
147-
/// When `is_collecting_in_band_lifetimes` is true, each lifetime is checked
148-
/// against this list to see if it is already in-scope, or if a definition
149-
/// needs to be created for it.
150-
///
151147
/// We always store a `normalize_to_macros_2_0()` version of the param-name in this
152148
/// vector.
153149
in_scope_lifetimes: Vec<ParamName>,
@@ -374,7 +370,7 @@ pub fn lower_crate<'a, 'hir>(
374370
task_context: None,
375371
current_item: None,
376372
lifetimes_to_define: Vec::new(),
377-
is_collecting_in_band_lifetimes: false,
373+
is_collecting_anonymous_lifetimes: false,
378374
in_scope_lifetimes: Vec::new(),
379375
allow_try_trait: Some([sym::try_trait_v2][..].into()),
380376
allow_gen_future: Some([sym::gen_future][..].into()),
@@ -718,13 +714,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
718714
&mut self,
719715
f: impl FnOnce(&mut Self) -> T,
720716
) -> (Vec<(Span, ParamName)>, T) {
721-
let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true);
717+
let was_collecting = std::mem::replace(&mut self.is_collecting_anonymous_lifetimes, true);
722718
let len = self.lifetimes_to_define.len();
723719

724720
let res = f(self);
725721

726722
let lifetimes_to_define = self.lifetimes_to_define.split_off(len);
727-
self.is_collecting_in_band_lifetimes = was_collecting;
723+
self.is_collecting_anonymous_lifetimes = was_collecting;
728724
(lifetimes_to_define, res)
729725
}
730726

@@ -741,7 +737,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
741737
// that collisions are ok here and this shouldn't
742738
// really show up for end-user.
743739
let (str_name, kind) = match hir_name {
744-
ParamName::Plain(ident) => (ident.name, hir::LifetimeParamKind::InBand),
740+
ParamName::Plain(ident) => (ident.name, hir::LifetimeParamKind::Explicit),
745741
ParamName::Fresh(_) => (kw::UnderscoreLifetime, hir::LifetimeParamKind::Elided),
746742
ParamName::Error => (kw::UnderscoreLifetime, hir::LifetimeParamKind::Error),
747743
};
@@ -765,38 +761,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
765761
}
766762
}
767763

768-
/// When there is a reference to some lifetime `'a`, and in-band
769-
/// lifetimes are enabled, then we want to push that lifetime into
770-
/// the vector of names to define later. In that case, it will get
771-
/// added to the appropriate generics.
772-
fn maybe_collect_in_band_lifetime(&mut self, ident: Ident) {
773-
if !self.is_collecting_in_band_lifetimes {
774-
return;
775-
}
776-
777-
if !self.sess.features_untracked().in_band_lifetimes {
778-
return;
779-
}
780-
781-
if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.normalize_to_macros_2_0())) {
782-
return;
783-
}
784-
785-
let hir_name = ParamName::Plain(ident);
786-
787-
if self.lifetimes_to_define.iter().any(|(_, lt_name)| {
788-
lt_name.normalize_to_macros_2_0() == hir_name.normalize_to_macros_2_0()
789-
}) {
790-
return;
791-
}
792-
793-
self.lifetimes_to_define.push((ident.span, hir_name));
794-
}
795-
796764
/// When we have either an elided or `'_` lifetime in an impl
797765
/// header, we convert it to an in-band lifetime.
798-
fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
799-
assert!(self.is_collecting_in_band_lifetimes);
766+
fn collect_fresh_anonymous_lifetime(&mut self, span: Span) -> ParamName {
767+
assert!(self.is_collecting_anonymous_lifetimes);
800768
let index = self.lifetimes_to_define.len() + self.in_scope_lifetimes.len();
801769
let hir_name = ParamName::Fresh(index);
802770
self.lifetimes_to_define.push((span, hir_name));
@@ -1938,7 +1906,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19381906
}
19391907
ident if ident.name == kw::UnderscoreLifetime => match self.anonymous_lifetime_mode {
19401908
AnonymousLifetimeMode::CreateParameter => {
1941-
let fresh_name = self.collect_fresh_in_band_lifetime(span);
1909+
let fresh_name = self.collect_fresh_anonymous_lifetime(span);
19421910
self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name))
19431911
}
19441912

@@ -1949,7 +1917,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19491917
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
19501918
},
19511919
ident => {
1952-
self.maybe_collect_in_band_lifetime(ident);
19531920
let param_name = ParamName::Plain(self.lower_ident(ident));
19541921
self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(param_name))
19551922
}
@@ -1993,8 +1960,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19931960

19941961
let (name, kind) = match param.kind {
19951962
GenericParamKind::Lifetime => {
1996-
let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
1997-
self.is_collecting_in_band_lifetimes = false;
1963+
let was_collecting_in_band = self.is_collecting_anonymous_lifetimes;
1964+
self.is_collecting_anonymous_lifetimes = false;
19981965

19991966
let lt = self
20001967
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
@@ -2017,7 +1984,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20171984
let kind =
20181985
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit };
20191986

2020-
self.is_collecting_in_band_lifetimes = was_collecting_in_band;
1987+
self.is_collecting_anonymous_lifetimes = was_collecting_in_band;
20211988

20221989
(param_name, kind)
20231990
}
@@ -2376,7 +2343,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23762343
// Hence `impl Foo for &u32` becomes `impl<'f> Foo for &'f u32` for some fresh
23772344
// `'f`.
23782345
AnonymousLifetimeMode::CreateParameter => {
2379-
let fresh_name = self.collect_fresh_in_band_lifetime(span);
2346+
let fresh_name = self.collect_fresh_anonymous_lifetime(span);
23802347
hir::Lifetime {
23812348
hir_id: self.next_id(),
23822349
span: self.lower_span(span),

compiler/rustc_error_codes/src/error_codes/E0687.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
In-band lifetimes cannot be used in `fn`/`Fn` syntax.
24

35
Erroneous code examples:
46

5-
```compile_fail,E0687
7+
```ignore (feature got removed)
68
#![feature(in_band_lifetimes)]
79
810
fn foo(x: fn(&'a u32)) {} // error!

compiler/rustc_error_codes/src/error_codes/E0688.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
In-band lifetimes were mixed with explicit lifetime binders.
24

35
Erroneous code example:
46

5-
```compile_fail,E0688
7+
```ignore (feature got removed)
68
#![feature(in_band_lifetimes)]
79
810
fn foo<'a>(x: &'a u32, y: &'b u32) {} // error!

compiler/rustc_feature/src/active.rs

-2
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,6 @@ declare_features! (
400400
(active, if_let_guard, "1.47.0", Some(51114), None),
401401
/// Allows using imported `main` function
402402
(active, imported_main, "1.53.0", Some(28937), None),
403-
/// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
404-
(active, in_band_lifetimes, "1.23.0", Some(44524), None),
405403
/// Allows inferring `'static` outlives requirements (RFC 2093).
406404
(active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
407405
/// Allows associated types in inherent impls.

compiler/rustc_feature/src/removed.rs

+3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ declare_features! (
104104
(removed, impl_trait_in_bindings, "1.55.0", Some(63065), None,
105105
Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),
106106
(removed, import_shadowing, "1.0.0", None, None, None),
107+
/// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
108+
(removed, in_band_lifetimes, "1.23.0", Some(44524), None,
109+
Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity")),
107110
/// Lazily evaluate constants. This allows constants to depend on type parameters.
108111
(removed, lazy_normalization_consts, "1.46.0", Some(72219), None, Some("superseded by `generic_const_exprs`")),
109112
/// Allows using the `#[link_args]` attribute.

compiler/rustc_hir/src/hir.rs

-5
Original file line numberDiff line numberDiff line change
@@ -470,11 +470,6 @@ pub enum LifetimeParamKind {
470470
// `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`).
471471
Explicit,
472472

473-
// Indicates that the lifetime definition was synthetically added
474-
// as a result of an in-band lifetime usage (e.g., in
475-
// `fn foo(x: &'a u8) -> &'a u8 { x }`).
476-
InBand,
477-
478473
// Indication that the lifetime was elided (e.g., in both cases in
479474
// `fn foo(x: &u8) -> &'_ u8 { x }`).
480475
Elided,

compiler/rustc_middle/src/middle/resolve_lifetime.rs

-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ use rustc_macros::HashStable;
1515
pub enum LifetimeDefOrigin {
1616
// Explicit binders like `fn foo<'a>(x: &'a u8)` or elided like `impl Foo<&u32>`
1717
ExplicitOrElided,
18-
// In-band declarations like `fn foo(x: &'a u8)`
19-
InBand,
2018
// Some kind of erroneous origin
2119
Error,
2220
}
@@ -25,7 +23,6 @@ impl LifetimeDefOrigin {
2523
pub fn from_param(param: &GenericParam<'_>) -> Self {
2624
match param.kind {
2725
GenericParamKind::Lifetime { kind } => match kind {
28-
LifetimeParamKind::InBand => LifetimeDefOrigin::InBand,
2926
LifetimeParamKind::Explicit => LifetimeDefOrigin::ExplicitOrElided,
3027
LifetimeParamKind::Elided => LifetimeDefOrigin::ExplicitOrElided,
3128
LifetimeParamKind::Error => LifetimeDefOrigin::Error,

compiler/rustc_resolve/src/late/diagnostics.rs

-11
Original file line numberDiff line numberDiff line change
@@ -1844,7 +1844,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
18441844
lifetime_ref
18451845
);
18461846
err.span_label(lifetime_ref.span, "undeclared lifetime");
1847-
let mut suggests_in_band = false;
18481847
let mut suggested_spans = vec![];
18491848
for missing in &self.missing_named_lifetime_spots {
18501849
match missing {
@@ -1860,7 +1859,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
18601859
}) {
18611860
(param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
18621861
} else {
1863-
suggests_in_band = true;
18641862
(generics.span, format!("<{}>", lifetime_ref))
18651863
};
18661864
if suggested_spans.contains(&span) {
@@ -1895,15 +1893,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
18951893
_ => {}
18961894
}
18971895
}
1898-
if self.tcx.sess.is_nightly_build()
1899-
&& !self.tcx.features().in_band_lifetimes
1900-
&& suggests_in_band
1901-
{
1902-
err.help(
1903-
"if you want to experiment with in-band lifetime bindings, \
1904-
add `#![feature(in_band_lifetimes)]` to the crate attributes",
1905-
);
1906-
}
19071896
err.emit();
19081897
}
19091898

compiler/rustc_resolve/src/late/lifetimes.rs

+2-68
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_hir::def_id::{DefIdMap, LocalDefId};
1616
use rustc_hir::hir_id::ItemLocalId;
1717
use rustc_hir::intravisit::{self, Visitor};
1818
use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
19-
use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind};
19+
use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet};
2020
use rustc_middle::hir::map::Map;
2121
use rustc_middle::hir::nested_filter;
2222
use rustc_middle::middle::resolve_lifetime::*;
@@ -1325,9 +1325,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
13251325
}
13261326

13271327
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
1328-
if !self.trait_definition_only {
1329-
check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params);
1330-
}
13311328
let scope = Scope::TraitRefBoundary { s: self.scope };
13321329
self.with(scope, |_, this| {
13331330
for param in generics.params {
@@ -1535,30 +1532,6 @@ impl ShadowKind {
15351532
}
15361533
}
15371534

1538-
fn check_mixed_explicit_and_in_band_defs(tcx: TyCtxt<'_>, params: &[hir::GenericParam<'_>]) {
1539-
let lifetime_params: Vec<_> = params
1540-
.iter()
1541-
.filter_map(|param| match param.kind {
1542-
GenericParamKind::Lifetime { kind, .. } => Some((kind, param.span)),
1543-
_ => None,
1544-
})
1545-
.collect();
1546-
let explicit = lifetime_params.iter().find(|(kind, _)| *kind == LifetimeParamKind::Explicit);
1547-
let in_band = lifetime_params.iter().find(|(kind, _)| *kind == LifetimeParamKind::InBand);
1548-
1549-
if let (Some((_, explicit_span)), Some((_, in_band_span))) = (explicit, in_band) {
1550-
struct_span_err!(
1551-
tcx.sess,
1552-
*in_band_span,
1553-
E0688,
1554-
"cannot mix in-band and explicit lifetime definitions"
1555-
)
1556-
.span_label(*in_band_span, "in-band lifetime definition here")
1557-
.span_label(*explicit_span, "explicit lifetime definition here")
1558-
.emit();
1559-
}
1560-
}
1561-
15621535
fn signal_shadowing_problem(tcx: TyCtxt<'_>, name: Symbol, orig: Original, shadower: Shadower) {
15631536
let mut err = if let (ShadowKind::Lifetime, ShadowKind::Lifetime) = (orig.kind, shadower.kind) {
15641537
// lifetime/lifetime shadowing is an error
@@ -1845,13 +1818,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
18451818
fn lifetime_deletion_span(&self, name: Ident, generics: &hir::Generics<'_>) -> Option<Span> {
18461819
generics.params.iter().enumerate().find_map(|(i, param)| {
18471820
if param.name.ident() == name {
1848-
let in_band = matches!(
1849-
param.kind,
1850-
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::InBand }
1851-
);
1852-
if in_band {
1853-
Some(param.span)
1854-
} else if generics.params.len() == 1 {
1821+
if generics.params.len() == 1 {
18551822
// if sole lifetime, remove the entire `<>` brackets
18561823
Some(generics.span)
18571824
} else {
@@ -2337,39 +2304,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23372304
}
23382305
}
23392306

2340-
// Check for fn-syntax conflicts with in-band lifetime definitions
2341-
if !self.trait_definition_only && self.is_in_fn_syntax {
2342-
match def {
2343-
Region::EarlyBound(_, _, LifetimeDefOrigin::InBand)
2344-
| Region::LateBound(_, _, _, LifetimeDefOrigin::InBand) => {
2345-
struct_span_err!(
2346-
self.tcx.sess,
2347-
lifetime_ref.span,
2348-
E0687,
2349-
"lifetimes used in `fn` or `Fn` syntax must be \
2350-
explicitly declared using `<...>` binders"
2351-
)
2352-
.span_label(lifetime_ref.span, "in-band lifetime definition")
2353-
.emit();
2354-
}
2355-
2356-
Region::Static
2357-
| Region::EarlyBound(
2358-
_,
2359-
_,
2360-
LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error,
2361-
)
2362-
| Region::LateBound(
2363-
_,
2364-
_,
2365-
_,
2366-
LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error,
2367-
)
2368-
| Region::LateBoundAnon(..)
2369-
| Region::Free(..) => {}
2370-
}
2371-
}
2372-
23732307
self.insert_lifetime(lifetime_ref, def);
23742308
} else {
23752309
self.emit_undeclared_lifetime_error(lifetime_ref);

src/test/ui/async-await/generics-and-bounds.rs

-11
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// edition:2018
33
// compile-flags: --crate-type lib
44

5-
#![feature(in_band_lifetimes)]
6-
75
use std::future::Future;
86

97
pub async fn simple_generic<T>() {}
@@ -73,10 +71,6 @@ pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future<Output = (
7371
async move { f.foo() }
7472
}
7573

76-
pub fn call_with_ref_block_in_band(f: &'a (impl Foo + 'a)) -> impl Future<Output = ()> + 'a {
77-
async move { f.foo() }
78-
}
79-
8074
pub fn async_block_with_same_generic_params_unifies() {
8175
let mut a = call_generic_bound_block(FooType);
8276
a = call_generic_bound_block(FooType);
@@ -91,9 +85,4 @@ pub fn async_block_with_same_generic_params_unifies() {
9185
let f_two = FooType;
9286
let mut d = call_with_ref_block(&f_one);
9387
d = call_with_ref_block(&f_two);
94-
95-
let f_one = FooType;
96-
let f_two = FooType;
97-
let mut d = call_with_ref_block_in_band(&f_one);
98-
d = call_with_ref_block_in_band(&f_two);
9988
}

src/test/ui/error-codes/E0261.stderr

-4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ LL | fn foo(x: &'a str) { }
55
| - ^^ undeclared lifetime
66
| |
77
| help: consider introducing lifetime `'a` here: `<'a>`
8-
|
9-
= help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
108

119
error[E0261]: use of undeclared lifetime name `'a`
1210
--> $DIR/E0261.rs:5:9
@@ -15,8 +13,6 @@ LL | struct Foo {
1513
| - help: consider introducing lifetime `'a` here: `<'a>`
1614
LL | x: &'a str,
1715
| ^^ undeclared lifetime
18-
|
19-
= help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
2016

2117
error: aborting due to 2 previous errors
2218

0 commit comments

Comments
 (0)