Skip to content

Commit 0c39eeb

Browse files
committed
only add hrtb as generic params to anon consts
1 parent 3ffbd66 commit 0c39eeb

File tree

4 files changed

+127
-74
lines changed

4 files changed

+127
-74
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
2-
use super::{ImplTraitContext, ImplTraitPosition};
2+
use super::{ImplTraitContext, ImplTraitPosition, LifetimeOrigin};
33
use crate::Arena;
44

55
use rustc_ast::node_id::NodeMap;
@@ -420,12 +420,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
420420
},
421421
);
422422

423-
let new_impl_items =
424-
self.with_in_scope_lifetime_defs(&ast_generics.params, |this| {
423+
let new_impl_items = self.with_in_scope_lifetime_defs(
424+
LifetimeOrigin::Other,
425+
&ast_generics.params,
426+
|this| {
425427
this.arena.alloc_from_iter(
426428
impl_items.iter().map(|item| this.lower_impl_item_ref(item)),
427429
)
428-
});
430+
},
431+
);
429432

430433
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
431434
// to not cause an assertion failure inside the `lower_defaultness` function.
@@ -1430,27 +1433,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
14301433
ref bounds,
14311434
span,
14321435
}) => {
1433-
self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
1434-
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1435-
bound_generic_params: this.lower_generic_params(
1436-
bound_generic_params,
1437-
&NodeMap::default(),
1438-
ImplTraitContext::disallowed(),
1439-
),
1440-
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
1441-
bounds: this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| {
1442-
match *bound {
1443-
// Ignore `?Trait` bounds.
1444-
// They were copied into type parameters already.
1445-
GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
1446-
_ => Some(
1447-
this.lower_param_bound(bound, ImplTraitContext::disallowed()),
1448-
),
1449-
}
1450-
})),
1451-
span,
1452-
})
1453-
})
1436+
self.with_in_scope_lifetime_defs(
1437+
LifetimeOrigin::Hrtb,
1438+
&bound_generic_params,
1439+
|this| {
1440+
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1441+
bound_generic_params: this.lower_generic_params(
1442+
bound_generic_params,
1443+
&NodeMap::default(),
1444+
ImplTraitContext::disallowed(),
1445+
),
1446+
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
1447+
bounds: this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| {
1448+
match *bound {
1449+
// Ignore `?Trait` bounds.
1450+
// They were copied into type parameters already.
1451+
GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
1452+
_ => {
1453+
Some(this.lower_param_bound(
1454+
bound,
1455+
ImplTraitContext::disallowed(),
1456+
))
1457+
}
1458+
}
1459+
})),
1460+
span,
1461+
})
1462+
},
1463+
)
14541464
}
14551465
WherePredicate::RegionPredicate(WhereRegionPredicate {
14561466
ref lifetime,

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 71 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ struct LoweringContext<'a, 'hir: 'a> {
155155
/// We always store a `normalize_to_macros_2_0()` version of the param-name in this
156156
/// vector.
157157
in_scope_lifetimes: Vec<ParamName>,
158+
/// The index of the first lifetime introduced using `for<'lt>`.
159+
///
160+
/// Used to only add lifetimes from binders as generics to anon consts.
161+
hrtb_start: Option<usize>,
158162

159163
current_module: hir::HirId,
160164

@@ -168,6 +172,12 @@ struct LoweringContext<'a, 'hir: 'a> {
168172
allow_gen_future: Option<Lrc<[Symbol]>>,
169173
}
170174

175+
#[derive(Copy, Clone)]
176+
enum LifetimeOrigin {
177+
Hrtb,
178+
Other,
179+
}
180+
171181
pub trait ResolverAstLowering {
172182
fn def_key(&mut self, id: DefId) -> DefKey;
173183

@@ -322,6 +332,7 @@ pub fn lower_crate<'a, 'hir>(
322332
lifetimes_to_define: Vec::new(),
323333
is_collecting_in_band_lifetimes: false,
324334
in_scope_lifetimes: Vec::new(),
335+
hrtb_start: None,
325336
allow_try_trait: Some([sym::try_trait][..].into()),
326337
allow_gen_future: Some([sym::gen_future][..].into()),
327338
}
@@ -853,6 +864,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
853864
// for them.
854865
fn with_in_scope_lifetime_defs<T>(
855866
&mut self,
867+
origin: LifetimeOrigin,
856868
params: &[GenericParam],
857869
f: impl FnOnce(&mut Self) -> T,
858870
) -> T {
@@ -864,9 +876,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
864876
_ => None,
865877
});
866878
self.in_scope_lifetimes.extend(lt_def_names);
879+
let hrtb_start = self.hrtb_start;
880+
if matches!(origin, LifetimeOrigin::Hrtb) && self.hrtb_start.is_none() {
881+
self.hrtb_start = Some(old_len);
882+
}
867883

868884
let res = f(self);
869885

886+
self.hrtb_start = hrtb_start;
870887
self.in_scope_lifetimes.truncate(old_len);
871888
res
872889
}
@@ -885,7 +902,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
885902
f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
886903
) -> (hir::Generics<'hir>, T) {
887904
let (in_band_defs, (mut lowered_generics, res)) =
888-
self.with_in_scope_lifetime_defs(&generics.params, |this| {
905+
self.with_in_scope_lifetime_defs(LifetimeOrigin::Other, &generics.params, |this| {
889906
this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| {
890907
let mut params = Vec::new();
891908
// Note: it is necessary to lower generics *before* calling `f`.
@@ -1225,21 +1242,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12251242
};
12261243
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
12271244
}
1228-
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
1229-
this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
1230-
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
1231-
generic_params: this.lower_generic_params(
1232-
&f.generic_params,
1233-
&NodeMap::default(),
1234-
ImplTraitContext::disallowed(),
1235-
),
1236-
unsafety: this.lower_unsafety(f.unsafety),
1237-
abi: this.lower_extern(f.ext),
1238-
decl: this.lower_fn_decl(&f.decl, None, false, None),
1239-
param_names: this.lower_fn_params_to_names(&f.decl),
1240-
}))
1245+
TyKind::BareFn(ref f) => {
1246+
self.with_in_scope_lifetime_defs(LifetimeOrigin::Hrtb, &f.generic_params, |this| {
1247+
this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
1248+
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
1249+
generic_params: this.lower_generic_params(
1250+
&f.generic_params,
1251+
&NodeMap::default(),
1252+
ImplTraitContext::disallowed(),
1253+
),
1254+
unsafety: this.lower_unsafety(f.unsafety),
1255+
abi: this.lower_extern(f.ext),
1256+
decl: this.lower_fn_decl(&f.decl, None, false, None),
1257+
param_names: this.lower_fn_params_to_names(&f.decl),
1258+
}))
1259+
})
12411260
})
1242-
}),
1261+
}
12431262
TyKind::Never => hir::TyKind::Never,
12441263
TyKind::Tup(ref tys) => {
12451264
hir::TyKind::Tup(self.arena.alloc_from_iter(
@@ -2243,28 +2262,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22432262
itctx.reborrow(),
22442263
);
22452264

2246-
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
2247-
// Any impl Trait types defined within this scope can capture
2248-
// lifetimes bound on this predicate.
2249-
let lt_def_names = p.bound_generic_params.iter().filter_map(|param| match param.kind {
2250-
GenericParamKind::Lifetime { .. } => Some(hir::LifetimeName::Param(
2251-
ParamName::Plain(param.ident.normalize_to_macros_2_0()),
2252-
)),
2253-
_ => None,
2254-
});
2255-
if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
2256-
capturable_lifetimes.extend(lt_def_names.clone());
2257-
}
2265+
let trait_ref = self.with_in_scope_lifetime_defs(
2266+
LifetimeOrigin::Hrtb,
2267+
&p.bound_generic_params,
2268+
|this| {
2269+
// Any impl Trait types defined within this scope can capture
2270+
// lifetimes bound on this predicate.
2271+
let lt_def_names =
2272+
p.bound_generic_params.iter().filter_map(|param| match param.kind {
2273+
GenericParamKind::Lifetime { .. } => Some(hir::LifetimeName::Param(
2274+
ParamName::Plain(param.ident.normalize_to_macros_2_0()),
2275+
)),
2276+
_ => None,
2277+
});
2278+
if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx
2279+
{
2280+
capturable_lifetimes.extend(lt_def_names.clone());
2281+
}
22582282

2259-
let res = this.lower_trait_ref(&p.trait_ref, itctx.reborrow());
2283+
let res = this.lower_trait_ref(&p.trait_ref, itctx.reborrow());
22602284

2261-
if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
2262-
for param in lt_def_names {
2263-
capturable_lifetimes.remove(&param);
2285+
if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx
2286+
{
2287+
for param in lt_def_names {
2288+
capturable_lifetimes.remove(&param);
2289+
}
22642290
}
2265-
}
2266-
res
2267-
});
2291+
res
2292+
},
2293+
);
22682294

22692295
hir::PolyTraitRef { bound_generic_params, trait_ref, span: p.span }
22702296
}
@@ -2341,20 +2367,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23412367
//
23422368
// We therefore add these lifetimes as additional generic parameters.
23432369

2344-
// FIXME(const_generics): We currently add all lifetimes as generic params,
2345-
// but as we already mention the parent generics this is not actually needed.
2346-
//
2347-
// Consider only adding explicit higher ranked lifetimes here.
2348-
23492370
// We only need `in_scope_lifetimes` because all in-band lifetimes are
23502371
// added to the generics of the parent.
2351-
let lifetime_params: Vec<(Span, ParamName)> = this
2352-
.in_scope_lifetimes
2353-
.iter()
2354-
.cloned()
2355-
.map(|name| (name.ident().span, name))
2356-
.collect();
2357-
2372+
let lifetime_params: Vec<(Span, ParamName)> =
2373+
if let Some(hrtb_start) = this.hrtb_start {
2374+
this.in_scope_lifetimes
2375+
.iter()
2376+
.skip(hrtb_start)
2377+
.cloned()
2378+
.map(|name| (name.ident().span, name))
2379+
.collect()
2380+
} else {
2381+
vec![]
2382+
};
23582383
let generic_params =
23592384
this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name)| {
23602385
this.lifetime_to_generic_param(span, hir_name, def_id)
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
// check-pass
21
#![feature(const_generics)]
32
#![allow(incomplete_features)]
43
#![deny(unused_lifetimes)]
54

6-
// FIXME(const_generics): this should error
7-
fn test<'a>() -> [u8; 3 + 4] { todo!() }
5+
fn err<'a>() -> [u8; 3 + 4] { todo!() }
6+
//~^ ERROR lifetime parameter `'a` never used
7+
8+
fn hrtb_err() where for<'a> [u8; 3 + 4]: Sized {}
9+
// FIXME(const_generics): This should error
810

911
fn ok1<'a>() -> [u8; { let _: &'a (); 3 }] { todo!() }
1012

@@ -13,4 +15,6 @@ fn ok2<'a>() -> [u8; 3 + 4] {
1315
todo!()
1416
}
1517

18+
fn hrtb_ok() where for<'a> [u8; { let _: &'a (); 3 }]: Sized {}
19+
1620
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: lifetime parameter `'a` never used
2+
--> $DIR/unused-lt.rs:5:8
3+
|
4+
LL | fn err<'a>() -> [u8; 3 + 4] { todo!() }
5+
| -^^- help: elide the unused lifetime
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/unused-lt.rs:3:9
9+
|
10+
LL | #![deny(unused_lifetimes)]
11+
| ^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)