Skip to content

Commit 39ff2a6

Browse files
authored
Rollup merge of #102884 - petrochenkov:liferib, r=cjgillot
resolve: Some cleanup, asserts and tests for lifetime ribs Follow up to #98279 and friends. r? ``@cjgillot``
2 parents cbe5e7b + f634106 commit 39ff2a6

File tree

3 files changed

+166
-65
lines changed

3 files changed

+166
-65
lines changed

compiler/rustc_resolve/src/late.rs

+77-65
Original file line numberDiff line numberDiff line change
@@ -224,22 +224,14 @@ enum LifetimeUseSet {
224224

225225
#[derive(Copy, Clone, Debug)]
226226
enum LifetimeRibKind {
227-
/// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
228-
Item,
229-
227+
// -- Ribs introducing named lifetimes
228+
//
230229
/// This rib declares generic parameters.
230+
/// Only for this kind the `LifetimeRib::bindings` field can be non-empty.
231231
Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
232232

233-
/// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
234-
/// generics. We are disallowing this until we can decide on how we want to handle non-'static
235-
/// lifetimes in const generics. See issue #74052 for discussion.
236-
ConstGeneric,
237-
238-
/// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
239-
/// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
240-
/// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
241-
AnonConst,
242-
233+
// -- Ribs introducing unnamed lifetimes
234+
//
243235
/// Create a new anonymous lifetime parameter and reference it.
244236
///
245237
/// If `report_in_path`, report an error when encountering lifetime elision in a path:
@@ -256,16 +248,31 @@ enum LifetimeRibKind {
256248
/// ```
257249
AnonymousCreateParameter { binder: NodeId, report_in_path: bool },
258250

251+
/// Replace all anonymous lifetimes by provided lifetime.
252+
Elided(LifetimeRes),
253+
254+
// -- Barrier ribs that stop lifetime lookup, or continue it but produce an error later.
255+
//
259256
/// Give a hard error when either `&` or `'_` is written. Used to
260257
/// rule out things like `where T: Foo<'_>`. Does not imply an
261258
/// error on default object bounds (e.g., `Box<dyn Foo>`).
262259
AnonymousReportError,
263260

264-
/// Replace all anonymous lifetimes by provided lifetime.
265-
Elided(LifetimeRes),
266-
267261
/// Signal we cannot find which should be the anonymous lifetime.
268262
ElisionFailure,
263+
264+
/// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
265+
/// generics. We are disallowing this until we can decide on how we want to handle non-'static
266+
/// lifetimes in const generics. See issue #74052 for discussion.
267+
ConstGeneric,
268+
269+
/// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
270+
/// This function will emit an error if `generic_const_exprs` is not enabled, the body
271+
/// identified by `body_id` is an anonymous constant and `lifetime_ref` is non-static.
272+
AnonConst,
273+
274+
/// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
275+
Item,
269276
}
270277

271278
#[derive(Copy, Clone, Debug)]
@@ -748,35 +755,31 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
748755
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
749756
match foreign_item.kind {
750757
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
751-
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
752-
this.with_generic_param_rib(
753-
&generics.params,
754-
ItemRibKind(HasGenericParams::Yes(generics.span)),
755-
LifetimeRibKind::Generics {
756-
binder: foreign_item.id,
757-
kind: LifetimeBinderKind::Item,
758-
span: generics.span,
759-
},
760-
|this| visit::walk_foreign_item(this, foreign_item),
761-
)
762-
});
758+
self.with_generic_param_rib(
759+
&generics.params,
760+
ItemRibKind(HasGenericParams::Yes(generics.span)),
761+
LifetimeRibKind::Generics {
762+
binder: foreign_item.id,
763+
kind: LifetimeBinderKind::Item,
764+
span: generics.span,
765+
},
766+
|this| visit::walk_foreign_item(this, foreign_item),
767+
);
763768
}
764769
ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
765-
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
766-
this.with_generic_param_rib(
767-
&generics.params,
768-
ItemRibKind(HasGenericParams::Yes(generics.span)),
769-
LifetimeRibKind::Generics {
770-
binder: foreign_item.id,
771-
kind: LifetimeBinderKind::Function,
772-
span: generics.span,
773-
},
774-
|this| visit::walk_foreign_item(this, foreign_item),
775-
)
776-
});
770+
self.with_generic_param_rib(
771+
&generics.params,
772+
ItemRibKind(HasGenericParams::Yes(generics.span)),
773+
LifetimeRibKind::Generics {
774+
binder: foreign_item.id,
775+
kind: LifetimeBinderKind::Function,
776+
span: generics.span,
777+
},
778+
|this| visit::walk_foreign_item(this, foreign_item),
779+
);
777780
}
778781
ForeignItemKind::Static(..) => {
779-
self.with_item_rib(|this| {
782+
self.with_static_rib(|this| {
780783
visit::walk_foreign_item(this, foreign_item);
781784
});
782785
}
@@ -1391,9 +1394,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13911394
return self.resolve_anonymous_lifetime(lifetime, false);
13921395
}
13931396

1394-
let mut indices = (0..self.lifetime_ribs.len()).rev();
1395-
for i in &mut indices {
1396-
let rib = &self.lifetime_ribs[i];
1397+
let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
1398+
while let Some(rib) = lifetime_rib_iter.next() {
13971399
let normalized_ident = ident.normalize_to_macros_2_0();
13981400
if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
13991401
self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
@@ -1423,9 +1425,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14231425
} else {
14241426
LifetimeUseSet::Many
14251427
}),
1426-
LifetimeRibKind::Generics { .. }
1427-
| LifetimeRibKind::ConstGeneric
1428-
| LifetimeRibKind::AnonConst => None,
1428+
LifetimeRibKind::Generics { .. } => None,
1429+
LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
1430+
span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
1431+
}
14291432
})
14301433
.unwrap_or(LifetimeUseSet::Many);
14311434
debug!(?use_ctxt, ?use_set);
@@ -1460,13 +1463,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14601463
);
14611464
return;
14621465
}
1463-
_ => {}
1466+
LifetimeRibKind::AnonymousCreateParameter { .. }
1467+
| LifetimeRibKind::Elided(_)
1468+
| LifetimeRibKind::Generics { .. }
1469+
| LifetimeRibKind::ElisionFailure
1470+
| LifetimeRibKind::AnonymousReportError => {}
14641471
}
14651472
}
14661473

14671474
let mut outer_res = None;
1468-
for i in indices {
1469-
let rib = &self.lifetime_ribs[i];
1475+
for rib in lifetime_rib_iter {
14701476
let normalized_ident = ident.normalize_to_macros_2_0();
14711477
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
14721478
outer_res = Some(outer);
@@ -1493,8 +1499,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14931499
count: 1,
14941500
};
14951501
let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
1496-
for i in (0..self.lifetime_ribs.len()).rev() {
1497-
let rib = &mut self.lifetime_ribs[i];
1502+
for rib in self.lifetime_ribs.iter().rev() {
14981503
debug!(?rib.kind);
14991504
match rib.kind {
15001505
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
@@ -1534,9 +1539,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15341539
return;
15351540
}
15361541
LifetimeRibKind::Item => break,
1537-
LifetimeRibKind::Generics { .. }
1538-
| LifetimeRibKind::ConstGeneric
1539-
| LifetimeRibKind::AnonConst => {}
1542+
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
1543+
LifetimeRibKind::AnonConst => {
1544+
// There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
1545+
span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
1546+
}
15401547
}
15411548
}
15421549
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
@@ -1751,9 +1758,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
17511758
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
17521759
break;
17531760
}
1754-
LifetimeRibKind::Generics { .. }
1755-
| LifetimeRibKind::ConstGeneric
1756-
| LifetimeRibKind::AnonConst => {}
1761+
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
1762+
LifetimeRibKind::AnonConst => {
1763+
// There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
1764+
span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
1765+
}
17571766
}
17581767
}
17591768

@@ -2204,7 +2213,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
22042213
}
22052214

22062215
ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
2207-
self.with_item_rib(|this| {
2216+
self.with_static_rib(|this| {
22082217
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
22092218
this.visit_ty(ty);
22102219
});
@@ -2399,11 +2408,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
23992408
self.label_ribs.pop();
24002409
}
24012410

2402-
fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
2411+
fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) {
24032412
let kind = ItemRibKind(HasGenericParams::No);
2404-
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
2405-
this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
2406-
})
2413+
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
24072414
}
24082415

24092416
// HACK(min_const_generics,const_evaluatable_unchecked): We
@@ -3938,7 +3945,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
39383945
fn_id: NodeId,
39393946
async_node_id: Option<(NodeId, Span)>,
39403947
) {
3941-
if let Some((async_node_id, _)) = async_node_id {
3948+
if let Some((async_node_id, span)) = async_node_id {
39423949
let mut extra_lifetime_params =
39433950
self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
39443951
for rib in self.lifetime_ribs.iter().rev() {
@@ -3952,7 +3959,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
39523959
extra_lifetime_params.extend(earlier_fresh);
39533960
}
39543961
}
3955-
_ => {}
3962+
LifetimeRibKind::Generics { .. } => {}
3963+
_ => {
3964+
// We are in a function definition. We should only find `Generics`
3965+
// and `AnonymousCreateParameter` inside the innermost `Item`.
3966+
span_bug!(span, "unexpected rib kind: {:?}", rib.kind)
3967+
}
39563968
}
39573969
}
39583970
self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![feature(inline_const)]
2+
3+
struct S<'a>(&'a u8);
4+
fn foo() {}
5+
6+
// Paren generic args in AnonConst
7+
fn a() -> [u8; foo::()] {
8+
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
9+
//~| ERROR mismatched types
10+
panic!()
11+
}
12+
13+
// Paren generic args in ConstGeneric
14+
fn b<const C: u8()>() {}
15+
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
16+
17+
// Paren generic args in AnonymousReportError
18+
fn c<T = u8()>() {}
19+
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
20+
//~| ERROR defaults for type parameters are only allowed in
21+
//~| WARN this was previously accepted
22+
23+
// Elided lifetime in path in ConstGeneric
24+
fn d<const C: S>() {}
25+
//~^ ERROR missing lifetime specifier
26+
//~| ERROR `S<'static>` is forbidden as the type of a const generic parameter
27+
28+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/unusual-rib-combinations.rs:24:15
3+
|
4+
LL | fn d<const C: S>() {}
5+
| ^ expected named lifetime parameter
6+
|
7+
help: consider introducing a named lifetime parameter
8+
|
9+
LL | fn d<'a, const C: S<'a>>() {}
10+
| +++ ++++
11+
12+
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
13+
--> $DIR/unusual-rib-combinations.rs:7:16
14+
|
15+
LL | fn a() -> [u8; foo::()] {
16+
| ^^^^^^^ only `Fn` traits may use parentheses
17+
18+
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
19+
--> $DIR/unusual-rib-combinations.rs:14:15
20+
|
21+
LL | fn b<const C: u8()>() {}
22+
| ^^^^ only `Fn` traits may use parentheses
23+
24+
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
25+
--> $DIR/unusual-rib-combinations.rs:18:10
26+
|
27+
LL | fn c<T = u8()>() {}
28+
| ^^^^ only `Fn` traits may use parentheses
29+
30+
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
31+
--> $DIR/unusual-rib-combinations.rs:18:6
32+
|
33+
LL | fn c<T = u8()>() {}
34+
| ^^^^^^^^
35+
|
36+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
37+
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
38+
= note: `#[deny(invalid_type_param_default)]` on by default
39+
40+
error[E0308]: mismatched types
41+
--> $DIR/unusual-rib-combinations.rs:7:16
42+
|
43+
LL | fn a() -> [u8; foo::()] {
44+
| ^^^^^^^ expected `usize`, found fn item
45+
|
46+
= note: expected type `usize`
47+
found fn item `fn() {foo}`
48+
49+
error: `S<'static>` is forbidden as the type of a const generic parameter
50+
--> $DIR/unusual-rib-combinations.rs:24:15
51+
|
52+
LL | fn d<const C: S>() {}
53+
| ^
54+
|
55+
= note: the only supported types are integers, `bool` and `char`
56+
= help: more complex types are supported with `#![feature(adt_const_params)]`
57+
58+
error: aborting due to 7 previous errors
59+
60+
Some errors have detailed explanations: E0106, E0214, E0308.
61+
For more information about an error, try `rustc --explain E0106`.

0 commit comments

Comments
 (0)