Skip to content

Commit 1b73e54

Browse files
committed
Forbid lifetime bounds in nested opaque types in binders
1 parent 3a08bd7 commit 1b73e54

File tree

13 files changed

+218
-74
lines changed

13 files changed

+218
-74
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13531353
&param.kind,
13541354
bounds,
13551355
PredicateOrigin::GenericParam,
1356+
itctx.reborrow(),
13561357
)
13571358
}));
13581359
predicates.extend(
@@ -1388,6 +1389,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13881389
kind: &GenericParamKind,
13891390
bounds: &'hir [hir::GenericBound<'hir>],
13901391
origin: PredicateOrigin,
1392+
itctx: ImplTraitContext<'_, 'hir>,
13911393
) -> Option<hir::WherePredicate<'hir>> {
13921394
// Do not create a clause if we do not have anything inside it.
13931395
if bounds.is_empty() {
@@ -1437,7 +1439,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
14371439
panic!("Missing resolution for lifetime {:?} at {:?}", id, ident.span)
14381440
});
14391441
let lt_id = self.resolver.next_node_id();
1440-
let lifetime = self.new_named_lifetime_with_res(lt_id, ident_span, ident, res);
1442+
let lifetime =
1443+
self.new_named_lifetime_with_res(lt_id, ident_span, ident, res, itctx);
14411444
Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
14421445
lifetime,
14431446
span,
@@ -1474,7 +1477,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
14741477
span,
14751478
}) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
14761479
span: self.lower_span(span),
1477-
lifetime: self.lower_lifetime(lifetime),
1480+
lifetime: self.lower_lifetime(
1481+
lifetime,
1482+
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1483+
),
14781484
bounds: self.lower_param_bounds(
14791485
bounds,
14801486
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 99 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ enum ImplTraitContext<'b, 'a> {
267267
ReturnPositionOpaqueTy {
268268
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
269269
origin: hir::OpaqueTyOrigin,
270+
/// Whether this is nested in another return position opaque type
271+
/// `None` if we aren't in any return position opaque type yet.
272+
nested: Option<bool>,
270273
},
271274
/// Impl trait in type aliases.
272275
TypeAliasesOpaqueTy,
@@ -303,7 +306,9 @@ impl<'a> ImplTraitContext<'_, 'a> {
303306
use self::ImplTraitContext::*;
304307
match self {
305308
Universal(params, bounds, parent) => Universal(params, bounds, *parent),
306-
ReturnPositionOpaqueTy { origin } => ReturnPositionOpaqueTy { origin: *origin },
309+
ReturnPositionOpaqueTy { origin, nested } => {
310+
ReturnPositionOpaqueTy { origin: *origin, nested: *nested }
311+
}
307312
TypeAliasesOpaqueTy => TypeAliasesOpaqueTy,
308313
Disallowed(pos) => Disallowed(*pos),
309314
}
@@ -1072,7 +1077,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10721077
itctx: ImplTraitContext<'_, 'hir>,
10731078
) -> hir::GenericArg<'hir> {
10741079
match arg {
1075-
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
1080+
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt, itctx)),
10761081
ast::GenericArg::Type(ty) => {
10771082
match ty.kind {
10781083
TyKind::Infer if self.sess.features_untracked().generic_arg_infer => {
@@ -1179,7 +1184,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11791184
id: start,
11801185
}
11811186
});
1182-
let lifetime = self.lower_lifetime(&region);
1187+
let lifetime = self.lower_lifetime(&region, itctx.reborrow());
11831188
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
11841189
}
11851190
TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| {
@@ -1239,7 +1244,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12391244
) => None,
12401245
GenericBound::Outlives(ref lifetime) => {
12411246
if lifetime_bound.is_none() {
1242-
lifetime_bound = Some(this.lower_lifetime(lifetime));
1247+
lifetime_bound =
1248+
Some(this.lower_lifetime(lifetime, itctx.reborrow()));
12431249
}
12441250
None
12451251
}
@@ -1254,17 +1260,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12541260
TyKind::ImplTrait(def_node_id, ref bounds) => {
12551261
let span = t.span;
12561262
match itctx {
1257-
ImplTraitContext::ReturnPositionOpaqueTy { origin } => self
1258-
.lower_opaque_impl_trait(span, origin, def_node_id, |this| {
1259-
this.lower_param_bounds(bounds, itctx)
1260-
}),
1263+
ImplTraitContext::ReturnPositionOpaqueTy { origin, nested } => self
1264+
.lower_opaque_impl_trait(
1265+
span,
1266+
origin,
1267+
def_node_id,
1268+
|this, itctx| this.lower_param_bounds(bounds, itctx),
1269+
ImplTraitContext::ReturnPositionOpaqueTy {
1270+
origin,
1271+
nested: match nested {
1272+
Some(_) => Some(true),
1273+
None => Some(false),
1274+
},
1275+
},
1276+
),
12611277
ImplTraitContext::TypeAliasesOpaqueTy => {
12621278
let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy;
12631279
self.lower_opaque_impl_trait(
12641280
span,
12651281
hir::OpaqueTyOrigin::TyAlias,
12661282
def_node_id,
1267-
|this| this.lower_param_bounds(bounds, nested_itctx),
1283+
|this, itctx| this.lower_param_bounds(bounds, itctx),
1284+
nested_itctx,
12681285
)
12691286
}
12701287
ImplTraitContext::Universal(
@@ -1299,6 +1316,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12991316
&GenericParamKind::Type { default: None },
13001317
hir_bounds,
13011318
hir::PredicateOrigin::ImplTrait,
1319+
ImplTraitContext::Universal(
1320+
in_band_ty_params,
1321+
in_band_ty_bounds,
1322+
parent_def_id,
1323+
),
13021324
) {
13031325
in_band_ty_bounds.push(preds)
13041326
}
@@ -1344,7 +1366,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13441366
span: Span,
13451367
origin: hir::OpaqueTyOrigin,
13461368
opaque_ty_node_id: NodeId,
1347-
lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
1369+
lower_bounds: impl FnOnce(&mut Self, ImplTraitContext<'_, 'hir>) -> hir::GenericBounds<'hir>,
1370+
mut itctx: ImplTraitContext<'_, 'hir>,
13481371
) -> hir::TyKind<'hir> {
13491372
// Make sure we know that some funky desugaring has been going on here.
13501373
// This is a first: there is code in other places like for loop
@@ -1358,13 +1381,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13581381
let mut collected_lifetimes = FxHashMap::default();
13591382
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
13601383
let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias {
1361-
lower_bounds(lctx)
1384+
lower_bounds(lctx, itctx.reborrow())
13621385
} else {
1363-
lctx.while_capturing_lifetimes(
1364-
opaque_ty_def_id,
1365-
&mut collected_lifetimes,
1366-
lower_bounds,
1367-
)
1386+
lctx.while_capturing_lifetimes(opaque_ty_def_id, &mut collected_lifetimes, |lctx| {
1387+
lower_bounds(lctx, itctx.reborrow())
1388+
})
13681389
};
13691390
debug!(?collected_lifetimes);
13701391

@@ -1412,7 +1433,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14121433
|(_, (span, _, p_name, res))| {
14131434
let id = self.resolver.next_node_id();
14141435
let ident = Ident::new(p_name.ident().name, span);
1415-
let l = self.new_named_lifetime_with_res(id, span, ident, res);
1436+
let l = self.new_named_lifetime_with_res(id, span, ident, res, itctx.reborrow());
14161437
hir::GenericArg::Lifetime(l)
14171438
},
14181439
));
@@ -1523,35 +1544,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15231544
}
15241545
}));
15251546

1547+
let context = match in_band_ty_params {
1548+
Some((node_id, _, _)) if kind.impl_trait_return_allowed() => {
1549+
let fn_def_id = self.resolver.local_def_id(node_id);
1550+
ImplTraitContext::ReturnPositionOpaqueTy {
1551+
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
1552+
nested: None,
1553+
}
1554+
}
1555+
_ => ImplTraitContext::Disallowed(match kind {
1556+
FnDeclKind::Fn | FnDeclKind::Inherent => {
1557+
unreachable!("fn should allow in-band lifetimes")
1558+
}
1559+
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnReturn,
1560+
FnDeclKind::Closure => ImplTraitPosition::ClosureReturn,
1561+
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
1562+
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
1563+
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
1564+
}),
1565+
};
1566+
15261567
let output = if let Some(ret_id) = make_ret_async {
15271568
self.lower_async_fn_ret_ty(
15281569
&decl.output,
15291570
in_band_ty_params.expect("`make_ret_async` but no `fn_def_id`").0,
15301571
ret_id,
1572+
context,
15311573
)
15321574
} else {
15331575
match decl.output {
1534-
FnRetTy::Ty(ref ty) => {
1535-
let context = match in_band_ty_params {
1536-
Some((node_id, _, _)) if kind.impl_trait_return_allowed() => {
1537-
let fn_def_id = self.resolver.local_def_id(node_id);
1538-
ImplTraitContext::ReturnPositionOpaqueTy {
1539-
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
1540-
}
1541-
}
1542-
_ => ImplTraitContext::Disallowed(match kind {
1543-
FnDeclKind::Fn | FnDeclKind::Inherent => {
1544-
unreachable!("fn should allow in-band lifetimes")
1545-
}
1546-
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnReturn,
1547-
FnDeclKind::Closure => ImplTraitPosition::ClosureReturn,
1548-
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
1549-
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
1550-
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
1551-
}),
1552-
};
1553-
hir::FnRetTy::Return(self.lower_ty(ty, context))
1554-
}
1576+
FnRetTy::Ty(ref ty) => hir::FnRetTy::Return(self.lower_ty(ty, context)),
15551577
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
15561578
}
15571579
};
@@ -1603,6 +1625,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16031625
output: &FnRetTy,
16041626
fn_node_id: NodeId,
16051627
opaque_ty_node_id: NodeId,
1628+
mut itctx: ImplTraitContext<'_, 'hir>,
16061629
) -> hir::FnRetTy<'hir> {
16071630
let span = output.span();
16081631

@@ -1765,7 +1788,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17651788
self.arena.alloc_from_iter(captures.into_iter().map(|(_, (span, _, p_name, res))| {
17661789
let id = self.resolver.next_node_id();
17671790
let ident = Ident::new(p_name.ident().name, span);
1768-
let l = self.new_named_lifetime_with_res(id, span, ident, res);
1791+
let l = self.new_named_lifetime_with_res(id, span, ident, res, itctx.reborrow());
17691792
hir::GenericArg::Lifetime(l)
17701793
}));
17711794

@@ -1794,6 +1817,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17941817
// generates.
17951818
let context = ImplTraitContext::ReturnPositionOpaqueTy {
17961819
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
1820+
nested: None,
17971821
};
17981822
self.lower_ty(ty, context)
17991823
}
@@ -1828,19 +1852,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
18281852
self.lower_trait_bound_modifier(*modifier),
18291853
),
18301854
GenericBound::Outlives(lifetime) => {
1831-
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
1855+
hir::GenericBound::Outlives(self.lower_lifetime(lifetime, itctx))
18321856
}
18331857
}
18341858
}
18351859

1836-
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
1860+
fn lower_lifetime(&mut self, l: &Lifetime, itctx: ImplTraitContext<'_, 'hir>) -> hir::Lifetime {
18371861
let span = self.lower_span(l.ident.span);
18381862
let ident = self.lower_ident(l.ident);
18391863
let res = self
18401864
.resolver
18411865
.get_lifetime_res(l.id)
18421866
.unwrap_or_else(|| panic!("Missing resolution for lifetime {:?} at {:?}", l, span));
1843-
self.new_named_lifetime_with_res(l.id, span, ident, res)
1867+
self.new_named_lifetime_with_res(l.id, span, ident, res, itctx)
18441868
}
18451869

18461870
#[tracing::instrument(level = "debug", skip(self))]
@@ -1850,6 +1874,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
18501874
span: Span,
18511875
ident: Ident,
18521876
res: LifetimeRes,
1877+
itctx: ImplTraitContext<'_, 'hir>,
18531878
) -> hir::Lifetime {
18541879
debug!(?self.captured_lifetimes);
18551880
let name = match res {
@@ -1858,21 +1883,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
18581883
let p_name = ParamName::Plain(ident);
18591884
if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) =
18601885
&mut self.captured_lifetimes
1861-
&& !binders_to_ignore.contains(&binder)
18621886
{
1863-
match captures.entry(param) {
1864-
Entry::Occupied(_) => {}
1865-
Entry::Vacant(v) => {
1866-
let p_id = self.resolver.next_node_id();
1867-
self.resolver.create_def(
1868-
*parent_def_id,
1869-
p_id,
1870-
DefPathData::LifetimeNs(p_name.ident().name),
1871-
ExpnId::root(),
1872-
span.with_parent(None),
1873-
);
1887+
if binders_to_ignore.contains(&binder) {
1888+
match itctx {
1889+
ImplTraitContext::ReturnPositionOpaqueTy {
1890+
nested: Some(true), ..
1891+
}
1892+
| ImplTraitContext::TypeAliasesOpaqueTy => {
1893+
let mut err = self.sess.struct_span_err(
1894+
span,
1895+
"higher kinded lifetime bounds on nested opaque types are not supported yet",
1896+
);
1897+
if let Some(&(span, _, _, _)) = captures.get(&param) {
1898+
err.span_note(span, "lifetime declared here");
1899+
}
1900+
err.help("See https://github.com/rust-lang/rust/issues/96194 for further details");
1901+
err.emit();
1902+
}
1903+
_ => {}
1904+
}
1905+
} else {
1906+
match captures.entry(param) {
1907+
Entry::Occupied(_) => {}
1908+
Entry::Vacant(v) => {
1909+
let p_id = self.resolver.next_node_id();
1910+
self.resolver.create_def(
1911+
*parent_def_id,
1912+
p_id,
1913+
DefPathData::LifetimeNs(p_name.ident().name),
1914+
ExpnId::root(),
1915+
span.with_parent(None),
1916+
);
18741917

1875-
v.insert((span, p_id, p_name, res));
1918+
v.insert((span, p_id, p_name, res));
1919+
}
18761920
}
18771921
}
18781922
}

compiler/rustc_ast_lowering/src/path.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
180180
segment: &PathSegment,
181181
param_mode: ParamMode,
182182
parenthesized_generic_args: ParenthesizedGenericArgs,
183-
itctx: ImplTraitContext<'_, 'hir>,
183+
mut itctx: ImplTraitContext<'_, 'hir>,
184184
) -> hir::PathSegment<'hir> {
185185
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
186186
let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
187187
let msg = "parenthesized type parameters may only be used with a `Fn` trait";
188188
match **generic_args {
189189
GenericArgs::AngleBracketed(ref data) => {
190-
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
190+
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx.reborrow())
191191
}
192192
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
193193
ParenthesizedGenericArgs::Ok => {
@@ -220,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
220220
self.lower_angle_bracketed_parameter_data(
221221
&data.as_angle_bracketed_args(),
222222
param_mode,
223-
itctx,
223+
itctx.reborrow(),
224224
)
225225
.0,
226226
false,
@@ -248,6 +248,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
248248
segment.id,
249249
segment.ident.span,
250250
&mut generic_args,
251+
itctx,
251252
);
252253
}
253254

@@ -277,6 +278,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
277278
segment_id: NodeId,
278279
segment_ident_span: Span,
279280
generic_args: &mut GenericArgsCtor<'hir>,
281+
mut itctx: ImplTraitContext<'_, 'hir>,
280282
) {
281283
let (start, end) = match self.resolver.get_lifetime_res(segment_id) {
282284
Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end),
@@ -305,10 +307,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
305307
0,
306308
(start.as_u32()..end.as_u32()).map(|i| {
307309
let id = NodeId::from_u32(i);
308-
let l = self.lower_lifetime(&Lifetime {
309-
id,
310-
ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span),
311-
});
310+
let l = self.lower_lifetime(
311+
&Lifetime {
312+
id,
313+
ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span),
314+
},
315+
itctx.reborrow(),
316+
);
312317
GenericArg::Lifetime(l)
313318
}),
314319
);

0 commit comments

Comments
 (0)