Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #99231

Merged
merged 24 commits into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9395103
Give a better error when `x dist` fails for an optional tool
jyn514 Jul 11, 2022
40ae7b5
Parse closure binders
WaffleLapkin Jun 2, 2022
97fcead
--bless tests
WaffleLapkin Jun 2, 2022
f89ef3c
Comment out expr size check
WaffleLapkin Jul 12, 2022
c2dbd62
Lower closure binders to hir & properly check them
WaffleLapkin Jul 12, 2022
0c28484
make for<> in closures a possible place to suggest adding named lifetime
WaffleLapkin Jun 30, 2022
577f3c6
add test for implicit stuff in signatures of closures with `for<>`
WaffleLapkin Jun 24, 2022
3ebb852
Add `LifetimeBinderKind::Closure`
WaffleLapkin Jul 3, 2022
df4fee9
Add an indirection for closures in `hir::ExprKind`
WaffleLapkin Jul 11, 2022
d2923b4
Add back expr size checks
WaffleLapkin Jul 11, 2022
b504a18
implement rustfmt formatting for `for<>` closure binders
WaffleLapkin Jun 30, 2022
30a3673
Add rustfmt test for formatting `for<>` before closures
WaffleLapkin Jul 3, 2022
9aa142b
Fix clippy build
WaffleLapkin Jun 30, 2022
031b2c5
Always use CreateParameter mode for function definitions.
cjgillot Jun 19, 2022
c7ac816
Clippy fallout.
cjgillot Jun 4, 2022
3b1b38d
Bless ui-fulldeps tests.
cjgillot Jun 4, 2022
5a20834
Add feature gate.
cjgillot Jun 22, 2022
f94484f
reduce scope of allow(rustc::potential_query_instability) in rustc_span
NiklasJonsson Jul 10, 2022
d431338
Stabilize `core::ffi:c_*` and rexport in `std::ffi`
joshtriplett Jun 20, 2022
f5e9cb5
Rollup merge of #97720 - cjgillot:all-fresh, r=petrochenkov
Dylan-DPC Jul 14, 2022
103b860
Rollup merge of #98315 - joshtriplett:stabilize-core-ffi-c, r=Mark-Si…
Dylan-DPC Jul 14, 2022
e5a86d7
Rollup merge of #98705 - WaffleLapkin:closure_binder, r=cjgillot
Dylan-DPC Jul 14, 2022
85159a4
Rollup merge of #99126 - NiklasJonsson:84447/rustc_span, r=petrochenkov
Dylan-DPC Jul 14, 2022
c1b43ef
Rollup merge of #99139 - jyn514:dist-tool-help, r=Mark-Simulacrum
Dylan-DPC Jul 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,7 @@ pub enum ExprKind {
/// A closure (e.g., `move |a, b, c| a + b + c`).
///
/// The final span is the span of the argument block `|...|`.
Closure(CaptureBy, Async, Movability, P<FnDecl>, P<Expr>, Span),
Closure(ClosureBinder, CaptureBy, Async, Movability, P<FnDecl>, P<Expr>, Span),
/// A block (`'label: { ... }`).
Block(P<Block>, Option<Label>),
/// An async block (`async move { ... }`).
Expand Down Expand Up @@ -1518,6 +1518,31 @@ pub enum Movability {
Movable,
}

/// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ClosureBinder {
/// The binder is not present, all closure lifetimes are inferred.
NotPresent,
/// The binder is present.
For {
/// Span of the whole `for<>` clause
///
/// ```text
/// for<'a, 'b> |_: &'a (), _: &'b ()| { ... }
/// ^^^^^^^^^^^ -- this
/// ```
span: Span,

/// Lifetimes in the `for<>` closure
///
/// ```text
/// for<'a, 'b> |_: &'a (), _: &'b ()| { ... }
/// ^^^^^^ -- this
/// ```
generic_params: P<[GenericParam]>,
},
}

/// Represents a macro invocation. The `path` indicates which macro
/// is being invoked, and the `args` are arguments passed to it.
#[derive(Clone, Encodable, Decodable, Debug)]
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ pub trait MutVisitor: Sized {
noop_visit_asyncness(a, self);
}

fn visit_closure_binder(&mut self, b: &mut ClosureBinder) {
noop_visit_closure_binder(b, self);
}

fn visit_block(&mut self, b: &mut P<Block>) {
noop_visit_block(b, self);
}
Expand Down Expand Up @@ -825,6 +829,17 @@ pub fn visit_constness<T: MutVisitor>(constness: &mut Const, vis: &mut T) {
}
}

pub fn noop_visit_closure_binder<T: MutVisitor>(binder: &mut ClosureBinder, vis: &mut T) {
match binder {
ClosureBinder::NotPresent => {}
ClosureBinder::For { span: _, generic_params } => {
let mut vec = std::mem::take(generic_params).into_vec();
vec.flat_map_in_place(|param| vis.flat_map_generic_param(param));
*generic_params = P::from_vec(vec);
}
}
}

pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut Async, vis: &mut T) {
match asyncness {
Async::Yes { span: _, closure_id, return_impl_trait_id } => {
Expand Down Expand Up @@ -1336,7 +1351,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(expr);
arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
}
ExprKind::Closure(_capture_by, asyncness, _movability, decl, body, span) => {
ExprKind::Closure(binder, _capture_by, asyncness, _movability, decl, body, span) => {
vis.visit_closure_binder(binder);
vis.visit_asyncness(asyncness);
vis.visit_fn_decl(decl);
vis.visit_expr(body);
Expand Down
25 changes: 19 additions & 6 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ pub enum FnKind<'a> {
Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),

/// E.g., `|x, y| body`.
Closure(&'a FnDecl, &'a Expr),
Closure(&'a ClosureBinder, &'a FnDecl, &'a Expr),
}

impl<'a> FnKind<'a> {
pub fn header(&self) -> Option<&'a FnHeader> {
match *self {
FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
FnKind::Closure(_, _) => None,
FnKind::Closure(_, _, _) => None,
}
}

Expand All @@ -77,7 +77,7 @@ impl<'a> FnKind<'a> {
pub fn decl(&self) -> &'a FnDecl {
match self {
FnKind::Fn(_, _, sig, _, _, _) => &sig.decl,
FnKind::Closure(decl, _) => decl,
FnKind::Closure(_, decl, _) => decl,
}
}

Expand Down Expand Up @@ -155,6 +155,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_generics(&mut self, g: &'ast Generics) {
walk_generics(self, g)
}
fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) {
walk_closure_binder(self, b)
}
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p)
}
Expand Down Expand Up @@ -636,6 +639,15 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics
walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
}

pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a ClosureBinder) {
match binder {
ClosureBinder::NotPresent => {}
ClosureBinder::For { generic_params, span: _ } => {
walk_list!(visitor, visit_generic_param, generic_params)
}
}
}

pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) {
match *predicate {
WherePredicate::BoundPredicate(WhereBoundPredicate {
Expand Down Expand Up @@ -682,7 +694,8 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa
walk_fn_decl(visitor, &sig.decl);
walk_list!(visitor, visit_block, body);
}
FnKind::Closure(decl, body) => {
FnKind::Closure(binder, decl, body) => {
visitor.visit_closure_binder(binder);
walk_fn_decl(visitor, decl);
visitor.visit_expr(body);
}
Expand Down Expand Up @@ -856,8 +869,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(subexpression);
walk_list!(visitor, visit_arm, arms);
}
ExprKind::Closure(_, _, _, ref decl, ref body, _decl_span) => {
visitor.visit_fn(FnKind::Closure(decl, body), expression.span, expression.id)
ExprKind::Closure(ref binder, _, _, _, ref decl, ref body, _decl_span) => {
visitor.visit_fn(FnKind::Closure(binder, decl, body), expression.span, expression.id)
}
ExprKind::Block(ref block, ref opt_label) => {
walk_list!(visitor, visit_label, opt_label);
Expand Down
71 changes: 56 additions & 15 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_expr_await(span, expr)
}
ExprKind::Closure(
ref binder,
capture_clause,
asyncness,
movability,
Expand All @@ -164,6 +165,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
) => {
if let Async::Yes { closure_id, .. } = asyncness {
self.lower_expr_async_closure(
binder,
capture_clause,
e.id,
closure_id,
Expand All @@ -173,6 +175,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
} else {
self.lower_expr_closure(
binder,
capture_clause,
e.id,
movability,
Expand Down Expand Up @@ -605,13 +608,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
});

// `static |_task_context| -> <ret_ty> { body }`:
let generator_kind = hir::ExprKind::Closure {
capture_clause,
bound_generic_params: &[],
fn_decl,
body,
fn_decl_span: self.lower_span(span),
movability: Some(hir::Movability::Static),
let generator_kind = {
let c = self.arena.alloc(hir::Closure {
binder: hir::ClosureBinder::Default,
capture_clause,
bound_generic_params: &[],
fn_decl,
body,
fn_decl_span: self.lower_span(span),
movability: Some(hir::Movability::Static),
});

hir::ExprKind::Closure(c)
};
let generator = hir::Expr {
hir_id: self.lower_node_id(closure_node_id),
Expand Down Expand Up @@ -831,14 +839,17 @@ impl<'hir> LoweringContext<'_, 'hir> {

fn lower_expr_closure(
&mut self,
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
movability: Movability,
decl: &FnDecl,
body: &Expr,
fn_decl_span: Span,
) -> hir::ExprKind<'hir> {
let (body, generator_option) = self.with_new_scopes(move |this| {
let (binder_clause, generic_params) = self.lower_closure_binder(binder);

let (body_id, generator_option) = self.with_new_scopes(move |this| {
let prev = this.current_item;
this.current_item = Some(fn_decl_span);
let mut generator_kind = None;
Expand All @@ -853,18 +864,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
(body_id, generator_option)
});

self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
self.with_lifetime_binder(closure_id, generic_params, |this, bound_generic_params| {
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = this.lower_fn_decl(decl, None, FnDeclKind::Closure, None);

hir::ExprKind::Closure {
let c = self.arena.alloc(hir::Closure {
binder: binder_clause,
capture_clause,
bound_generic_params,
fn_decl,
body,
body: body_id,
fn_decl_span: this.lower_span(fn_decl_span),
movability: generator_option,
}
});

hir::ExprKind::Closure(c)
})
}

Expand Down Expand Up @@ -906,15 +920,40 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn lower_closure_binder<'c>(
&mut self,
binder: &'c ClosureBinder,
) -> (hir::ClosureBinder, &'c [GenericParam]) {
let (binder, params) = match binder {
ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]),
&ClosureBinder::For { span, ref generic_params } => {
let span = self.lower_span(span);
(hir::ClosureBinder::For { span }, &**generic_params)
}
};

(binder, params)
}

fn lower_expr_async_closure(
&mut self,
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
inner_closure_id: NodeId,
decl: &FnDecl,
body: &Expr,
fn_decl_span: Span,
) -> hir::ExprKind<'hir> {
if let &ClosureBinder::For { span, .. } = binder {
self.tcx.sess.span_err(
span,
"`for<...>` binders on `async` closures are not currently supported",
);
}

let (binder_clause, generic_params) = self.lower_closure_binder(binder);

let outer_decl =
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };

Expand Down Expand Up @@ -952,20 +991,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
body_id
});

self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
self.with_lifetime_binder(closure_id, generic_params, |this, bound_generic_params| {
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);

hir::ExprKind::Closure {
let c = self.arena.alloc(hir::Closure {
binder: binder_clause,
capture_clause,
bound_generic_params,
fn_decl,
body,
fn_decl_span: this.lower_span(fn_decl_span),
movability: None,
}
});
hir::ExprKind::Closure(c)
})
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
.emit();
}

if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
self.check_late_bound_lifetime_defs(generic_params);
}

if let FnKind::Fn(
_,
_,
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
"async closures are unstable",
"to use an async block, remove the `||`: `async {`"
);
gate_all!(
closure_lifetime_binder,
"`for<...>` binders for closures are experimental",
"consider removing `for<...>`"
);
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
gate_all!(generators, "yield syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental");
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,13 +389,15 @@ impl<'a> State<'a> {
self.bclose(expr.span, empty);
}
ast::ExprKind::Closure(
ref binder,
capture_clause,
asyncness,
movability,
ref decl,
ref body,
_,
) => {
self.print_closure_binder(binder);
self.print_movability(movability);
self.print_asyncness(asyncness);
self.print_capture_clause(capture_clause);
Expand Down Expand Up @@ -594,6 +596,15 @@ impl<'a> State<'a> {
self.end(); // Close enclosing cbox.
}

fn print_closure_binder(&mut self, binder: &ast::ClosureBinder) {
match binder {
ast::ClosureBinder::NotPresent => {}
ast::ClosureBinder::For { generic_params, .. } => {
self.print_formal_generic_params(&generic_params)
}
}
}

fn print_movability(&mut self, movability: ast::Movability) {
match movability {
ast::Movability::Static => self.word_space("static"),
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(local_did);
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
if let hir::ExprKind::Closure { body, fn_decl_span, .. } = expr {
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
for (captured_place, place) in self
.infcx
.tcx
Expand All @@ -904,11 +904,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if target_place == place.as_ref() =>
{
debug!("closure_span: found captured local {:?}", place);
let body = self.infcx.tcx.hir().body(*body);
let body = self.infcx.tcx.hir().body(body);
let generator_kind = body.generator_kind();

return Some((
*fn_decl_span,
fn_decl_span,
generator_kind,
captured_place.get_capture_kind_span(self.infcx.tcx),
captured_place.get_path_span(self.infcx.tcx),
Expand Down
Loading