Skip to content

Commit 10f4ce3

Browse files
committedJun 22, 2022
Auto merge of #98279 - cjgillot:all-fresh-nofn, r=petrochenkov
Create elided lifetime parameters for function-like types Split from #97720 This PR refactor lifetime generic parameters in bare function types and parenthesized traits to introduce the additional required lifetimes as fresh parameters in a `for<>` bound. This PR does the same to lifetimes appearing in closure signatures, and as-if introducing `for<>` bounds on closures (without the associated change in semantics). r? `@petrochenkov`
2 parents 89a0783 + 576661c commit 10f4ce3

File tree

28 files changed

+808
-599
lines changed

28 files changed

+808
-599
lines changed
 

‎compiler/rustc_ast_lowering/src/expr.rs

+34-23
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
165165
if let Async::Yes { closure_id, .. } = asyncness {
166166
self.lower_expr_async_closure(
167167
capture_clause,
168+
e.id,
168169
closure_id,
169170
decl,
170171
body,
@@ -173,6 +174,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
173174
} else {
174175
self.lower_expr_closure(
175176
capture_clause,
177+
e.id,
176178
movability,
177179
decl,
178180
body,
@@ -604,6 +606,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
604606
// `static |_task_context| -> <ret_ty> { body }`:
605607
let generator_kind = hir::ExprKind::Closure {
606608
capture_clause,
609+
bound_generic_params: &[],
607610
fn_decl,
608611
body,
609612
fn_decl_span: self.lower_span(span),
@@ -828,6 +831,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
828831
fn lower_expr_closure(
829832
&mut self,
830833
capture_clause: CaptureBy,
834+
closure_id: NodeId,
831835
movability: Movability,
832836
decl: &FnDecl,
833837
body: &Expr,
@@ -848,16 +852,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
848852
(body_id, generator_option)
849853
});
850854

851-
// Lower outside new scope to preserve `is_in_loop_condition`.
852-
let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
853-
854-
hir::ExprKind::Closure {
855-
capture_clause,
856-
fn_decl,
857-
body,
858-
fn_decl_span: self.lower_span(fn_decl_span),
859-
movability: generator_option,
860-
}
855+
self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
856+
// Lower outside new scope to preserve `is_in_loop_condition`.
857+
let fn_decl = this.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
858+
859+
hir::ExprKind::Closure {
860+
capture_clause,
861+
bound_generic_params,
862+
fn_decl,
863+
body,
864+
fn_decl_span: this.lower_span(fn_decl_span),
865+
movability: generator_option,
866+
}
867+
})
861868
}
862869

863870
fn generator_movability_for_fn(
@@ -897,6 +904,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
897904
&mut self,
898905
capture_clause: CaptureBy,
899906
closure_id: NodeId,
907+
inner_closure_id: NodeId,
900908
decl: &FnDecl,
901909
body: &Expr,
902910
fn_decl_span: Span,
@@ -927,7 +935,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
927935
if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
928936
let async_body = this.make_async_expr(
929937
capture_clause,
930-
closure_id,
938+
inner_closure_id,
931939
async_ret_ty,
932940
body.span,
933941
hir::AsyncGeneratorKind::Closure,
@@ -938,18 +946,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
938946
body_id
939947
});
940948

941-
// We need to lower the declaration outside the new scope, because we
942-
// have to conserve the state of being inside a loop condition for the
943-
// closure argument types.
944-
let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
945-
946-
hir::ExprKind::Closure {
947-
capture_clause,
948-
fn_decl,
949-
body,
950-
fn_decl_span: self.lower_span(fn_decl_span),
951-
movability: None,
952-
}
949+
self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
950+
// We need to lower the declaration outside the new scope, because we
951+
// have to conserve the state of being inside a loop condition for the
952+
// closure argument types.
953+
let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
954+
955+
hir::ExprKind::Closure {
956+
capture_clause,
957+
bound_generic_params,
958+
fn_decl,
959+
body,
960+
fn_decl_span: this.lower_span(fn_decl_span),
961+
movability: None,
962+
}
963+
})
953964
}
954965

955966
/// Destructure the LHS of complex assignments.

‎compiler/rustc_ast_lowering/src/item.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1386,16 +1386,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
13861386

13871387
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> =
13881388
self.lower_generic_params_mut(&generics.params).collect();
1389+
1390+
// Introduce extra lifetimes if late resolution tells us to.
1391+
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
1392+
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
1393+
self.lifetime_res_to_generic_param(ident, node_id, res)
1394+
}));
1395+
13891396
let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
13901397
let where_clause_span = self.lower_span(generics.where_clause.span);
13911398
let span = self.lower_span(generics.span);
13921399
let res = f(self);
13931400

1394-
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
13951401
let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
1396-
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
1397-
self.lifetime_res_to_generic_param(ident, node_id, res)
1398-
}));
13991402
params.extend(impl_trait_defs.into_iter());
14001403

14011404
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);

‎compiler/rustc_ast_lowering/src/lib.rs

+55-20
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,12 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
223223
}
224224

225225
/// Obtain the list of lifetimes parameters to add to an item.
226+
///
227+
/// Extra lifetime parameters should only be added in places that can appear
228+
/// as a `binder` in `LifetimeRes`.
229+
///
230+
/// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring
231+
/// should appear at the enclosing `PolyTraitRef`.
226232
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
227233
self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
228234
}
@@ -721,6 +727,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
721727
}
722728

723729
/// Converts a lifetime into a new generic parameter.
730+
#[tracing::instrument(level = "debug", skip(self))]
724731
fn lifetime_res_to_generic_param(
725732
&mut self,
726733
ident: Ident,
@@ -731,7 +738,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
731738
LifetimeRes::Param { .. } => {
732739
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
733740
}
734-
LifetimeRes::Fresh { .. } => (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided),
741+
LifetimeRes::Fresh { param, .. } => {
742+
// Late resolution delegates to us the creation of the `LocalDefId`.
743+
let _def_id = self.create_def(
744+
self.current_hir_id_owner,
745+
param,
746+
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
747+
);
748+
debug!(?_def_id);
749+
750+
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided)
751+
}
735752
LifetimeRes::Static | LifetimeRes::Error => return None,
736753
res => panic!(
737754
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
@@ -777,11 +794,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
777794
/// Register a binder to be ignored for lifetime capture.
778795
#[tracing::instrument(level = "debug", skip(self, f))]
779796
#[inline]
780-
fn with_lifetime_binder<T>(&mut self, binder: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
797+
fn with_lifetime_binder<T>(
798+
&mut self,
799+
binder: NodeId,
800+
generic_params: &[GenericParam],
801+
f: impl FnOnce(&mut Self, &'hir [hir::GenericParam<'hir>]) -> T,
802+
) -> T {
803+
let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect();
804+
let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
805+
debug!(?extra_lifetimes);
806+
generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
807+
self.lifetime_res_to_generic_param(ident, node_id, res)
808+
}));
809+
let generic_params = self.arena.alloc_from_iter(generic_params);
810+
debug!(?generic_params);
811+
781812
if let Some(ctxt) = &mut self.captured_lifetimes {
782813
ctxt.binders_to_ignore.insert(binder);
783814
}
784-
let ret = f(self);
815+
let ret = f(self, generic_params);
785816
if let Some(ctxt) = &mut self.captured_lifetimes {
786817
ctxt.binders_to_ignore.remove(&binder);
787818
}
@@ -1178,15 +1209,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11781209
let lifetime = self.lower_lifetime(&region);
11791210
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
11801211
}
1181-
TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| {
1182-
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
1183-
generic_params: this.lower_generic_params(&f.generic_params),
1184-
unsafety: this.lower_unsafety(f.unsafety),
1185-
abi: this.lower_extern(f.ext),
1186-
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
1187-
param_names: this.lower_fn_params_to_names(&f.decl),
1188-
}))
1189-
}),
1212+
TyKind::BareFn(ref f) => {
1213+
self.with_lifetime_binder(t.id, &f.generic_params, |this, generic_params| {
1214+
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
1215+
generic_params,
1216+
unsafety: this.lower_unsafety(f.unsafety),
1217+
abi: this.lower_extern(f.ext),
1218+
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
1219+
param_names: this.lower_fn_params_to_names(&f.decl),
1220+
}))
1221+
})
1222+
}
11901223
TyKind::Never => hir::TyKind::Never,
11911224
TyKind::Tup(ref tys) => hir::TyKind::Tup(
11921225
self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
@@ -1814,8 +1847,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
18141847
}
18151848
hir::LifetimeName::Param(param, p_name)
18161849
}
1817-
LifetimeRes::Fresh { mut param, binder } => {
1850+
LifetimeRes::Fresh { param, binder } => {
18181851
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
1852+
let mut param = self.local_def_id(param);
18191853
if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
18201854
if !captured_lifetimes.binders_to_ignore.contains(&binder) {
18211855
match captured_lifetimes.captures.entry(param) {
@@ -1952,13 +1986,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19521986
p: &PolyTraitRef,
19531987
itctx: ImplTraitContext,
19541988
) -> hir::PolyTraitRef<'hir> {
1955-
let bound_generic_params = self.lower_generic_params(&p.bound_generic_params);
1956-
1957-
let trait_ref = self.with_lifetime_binder(p.trait_ref.ref_id, |this| {
1958-
this.lower_trait_ref(&p.trait_ref, itctx)
1959-
});
1960-
1961-
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
1989+
self.with_lifetime_binder(
1990+
p.trait_ref.ref_id,
1991+
&p.bound_generic_params,
1992+
|this, bound_generic_params| {
1993+
let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx);
1994+
hir::PolyTraitRef { bound_generic_params, trait_ref, span: this.lower_span(p.span) }
1995+
},
1996+
)
19621997
}
19631998

19641999
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {

‎compiler/rustc_ast_lowering/src/path.rs

+22-29
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
191191
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
192192
}
193193
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
194-
ParenthesizedGenericArgs::Ok => {
195-
self.lower_parenthesized_parameter_data(segment.id, data)
196-
}
194+
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
197195
ParenthesizedGenericArgs::Err => {
198196
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
199197
err.span_label(data.span, "only `Fn` traits may use parentheses");
@@ -351,39 +349,34 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
351349

352350
fn lower_parenthesized_parameter_data(
353351
&mut self,
354-
id: NodeId,
355352
data: &ParenthesizedArgs,
356353
) -> (GenericArgsCtor<'hir>, bool) {
357354
// Switch to `PassThrough` mode for anonymous lifetimes; this
358355
// means that we permit things like `&Ref<T>`, where `Ref` has
359356
// a hidden lifetime parameter. This is needed for backwards
360357
// compatibility, even in contexts like an impl header where
361358
// we generally don't permit such things (see #51008).
362-
self.with_lifetime_binder(id, |this| {
363-
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
364-
let inputs = this.arena.alloc_from_iter(inputs.iter().map(|ty| {
365-
this.lower_ty_direct(
366-
ty,
367-
ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam),
368-
)
369-
}));
370-
let output_ty = match output {
371-
FnRetTy::Ty(ty) => this
372-
.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)),
373-
FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
374-
};
375-
let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
376-
let binding = this.output_ty_binding(output_ty.span, output_ty);
377-
(
378-
GenericArgsCtor {
379-
args,
380-
bindings: arena_vec![this; binding],
381-
parenthesized: true,
382-
span: data.inputs_span,
383-
},
384-
false,
385-
)
386-
})
359+
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
360+
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| {
361+
self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
362+
}));
363+
let output_ty = match output {
364+
FnRetTy::Ty(ty) => {
365+
self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
366+
}
367+
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
368+
};
369+
let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
370+
let binding = self.output_ty_binding(output_ty.span, output_ty);
371+
(
372+
GenericArgsCtor {
373+
args,
374+
bindings: arena_vec![self; binding],
375+
parenthesized: true,
376+
span: data.inputs_span,
377+
},
378+
false,
379+
)
387380
}
388381

389382
/// An associated type binding `Output = $ty`.

‎compiler/rustc_borrowck/src/diagnostics/region_name.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
254254
/// *user* has a name for. In that case, we'll be able to map
255255
/// `fr` to a `Region<'tcx>`, and that region will be one of
256256
/// named variants.
257+
#[tracing::instrument(level = "trace", skip(self))]
257258
fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
258259
let error_region = self.to_error_region(fr)?;
259260

@@ -290,7 +291,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
290291
if free_region.bound_region.is_named() {
291292
// A named region that is actually named.
292293
Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) })
293-
} else {
294+
} else if let hir::IsAsync::Async = tcx.asyncness(self.mir_hir_id().owner) {
294295
// If we spuriously thought that the region is named, we should let the
295296
// system generate a true name for error messages. Currently this can
296297
// happen if we have an elided name in an async fn for example: the
@@ -301,6 +302,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
301302
name,
302303
source: RegionNameSource::AnonRegionFromAsyncFn(span),
303304
})
305+
} else {
306+
None
304307
}
305308
}
306309

@@ -362,6 +365,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
362365
/// | fn foo(x: &u32) { .. }
363366
/// ------- fully elaborated type of `x` is `&'1 u32`
364367
/// ```
368+
#[tracing::instrument(level = "trace", skip(self))]
365369
fn give_name_if_anonymous_region_appears_in_arguments(
366370
&self,
367371
fr: RegionVid,
@@ -651,6 +655,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
651655
/// | let x = Some(&22);
652656
/// - fully elaborated type of `x` is `Option<&'1 u32>`
653657
/// ```
658+
#[tracing::instrument(level = "trace", skip(self))]
654659
fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
655660
let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
656661
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
@@ -670,6 +675,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
670675
/// must be a closure since, in a free fn, such an argument would
671676
/// have to either also appear in an argument (if using elision)
672677
/// or be early bound (named, not in argument).
678+
#[tracing::instrument(level = "trace", skip(self))]
673679
fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
674680
let tcx = self.infcx.tcx;
675681
let hir = tcx.hir();
@@ -801,6 +807,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
801807
}
802808
}
803809

810+
#[tracing::instrument(level = "trace", skip(self))]
804811
fn give_name_if_anonymous_region_appears_in_yield_ty(
805812
&self,
806813
fr: RegionVid,

0 commit comments

Comments
 (0)
Please sign in to comment.