mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Parse closure binders
This is first step in implementing RFC 3216. - Parse `for<'a>` before closures in ast - Error in lowering - Add `closure_lifetime_binder` feature
This commit is contained in:
parent
fbdb07f4e7
commit
40ae7b5b8e
@ -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 { ... }`).
|
||||
@ -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)]
|
||||
|
@ -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);
|
||||
}
|
||||
@ -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 } => {
|
||||
@ -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);
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
@ -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 { span: _, generic_params } => {
|
||||
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 {
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
|
@ -155,6 +155,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.lower_expr_await(span, expr)
|
||||
}
|
||||
ExprKind::Closure(
|
||||
ref binder,
|
||||
capture_clause,
|
||||
asyncness,
|
||||
movability,
|
||||
@ -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,
|
||||
@ -173,6 +175,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
)
|
||||
} else {
|
||||
self.lower_expr_closure(
|
||||
binder,
|
||||
capture_clause,
|
||||
e.id,
|
||||
movability,
|
||||
@ -831,6 +834,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
fn lower_expr_closure(
|
||||
&mut self,
|
||||
binder: &ClosureBinder,
|
||||
capture_clause: CaptureBy,
|
||||
closure_id: NodeId,
|
||||
movability: Movability,
|
||||
@ -838,6 +842,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
body: &Expr,
|
||||
fn_decl_span: Span,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
// FIXME(waffle): lower binder
|
||||
if let &ClosureBinder::For { span, .. } = binder {
|
||||
self.sess
|
||||
.struct_span_err(span, "`for<...>` binders for closures are not yet supported")
|
||||
.help("consider removing `for<...>`")
|
||||
.emit();
|
||||
}
|
||||
|
||||
let (body, generator_option) = self.with_new_scopes(move |this| {
|
||||
let prev = this.current_item;
|
||||
this.current_item = Some(fn_decl_span);
|
||||
@ -908,6 +920,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
fn lower_expr_async_closure(
|
||||
&mut self,
|
||||
binder: &ClosureBinder,
|
||||
capture_clause: CaptureBy,
|
||||
closure_id: NodeId,
|
||||
inner_closure_id: NodeId,
|
||||
@ -915,6 +928,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
body: &Expr,
|
||||
fn_decl_span: Span,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
// FIXME(waffle): lower binder
|
||||
if let &ClosureBinder::For { span, .. } = binder {
|
||||
self.sess
|
||||
.struct_span_err(
|
||||
span,
|
||||
"`for<...>` binders for async closures are not yet supported",
|
||||
)
|
||||
.help("consider removing `for<...>`")
|
||||
.emit();
|
||||
}
|
||||
|
||||
let outer_decl =
|
||||
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
||||
|
||||
|
@ -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(
|
||||
_,
|
||||
_,
|
||||
|
@ -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");
|
||||
|
@ -389,6 +389,7 @@ impl<'a> State<'a> {
|
||||
self.bclose(expr.span, empty);
|
||||
}
|
||||
ast::ExprKind::Closure(
|
||||
ref binder,
|
||||
capture_clause,
|
||||
asyncness,
|
||||
movability,
|
||||
@ -396,6 +397,7 @@ impl<'a> State<'a> {
|
||||
ref body,
|
||||
_,
|
||||
) => {
|
||||
self.print_closure_binder(binder);
|
||||
self.print_movability(movability);
|
||||
self.print_asyncness(asyncness);
|
||||
self.print_capture_clause(capture_clause);
|
||||
@ -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"),
|
||||
|
@ -294,7 +294,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
| ExprKind::Block(_, _)
|
||||
| ExprKind::Box(_)
|
||||
| ExprKind::Break(_, _)
|
||||
| ExprKind::Closure(_, _, _, _, _, _)
|
||||
| ExprKind::Closure(_, _, _, _, _, _, _)
|
||||
| ExprKind::ConstBlock(_)
|
||||
| ExprKind::Continue(_)
|
||||
| ExprKind::Err
|
||||
|
@ -520,6 +520,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
self.expr(
|
||||
span,
|
||||
ast::ExprKind::Closure(
|
||||
ast::ClosureBinder::NotPresent,
|
||||
ast::CaptureBy::Ref,
|
||||
ast::Async::No,
|
||||
ast::Movability::Movable,
|
||||
|
@ -331,6 +331,8 @@ declare_features! (
|
||||
(active, cfg_target_thread_local, "1.7.0", Some(29594), None),
|
||||
/// Allow conditional compilation depending on rust version
|
||||
(active, cfg_version, "1.45.0", Some(64796), None),
|
||||
/// Allows `for<...>` on closures and generators.
|
||||
(active, closure_lifetime_binder, "1.64.0", Some(97362), None),
|
||||
/// Allows `#[track_caller]` on closures and generators.
|
||||
(active, closure_track_caller, "1.57.0", Some(87417), None),
|
||||
/// Allows to use the `#[cmse_nonsecure_entry]` attribute.
|
||||
|
@ -218,7 +218,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
||||
// Explicitly check for lints associated with 'closure_id', since
|
||||
// it does not have a corresponding AST node
|
||||
match e.kind {
|
||||
ast::ExprKind::Closure(_, ast::Async::Yes { closure_id, .. }, ..)
|
||||
ast::ExprKind::Closure(_, _, ast::Async::Yes { closure_id, .. }, ..)
|
||||
| ast::ExprKind::Async(_, closure_id, ..) => self.check_id(closure_id),
|
||||
_ => {}
|
||||
}
|
||||
|
@ -15,10 +15,10 @@ use rustc_ast::util::classify;
|
||||
use rustc_ast::util::literal::LitError;
|
||||
use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
|
||||
use rustc_ast::visit::Visitor;
|
||||
use rustc_ast::StmtKind;
|
||||
use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, Lit, UnOp, DUMMY_NODE_ID};
|
||||
use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
|
||||
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
|
||||
use rustc_ast::{ClosureBinder, StmtKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
|
||||
@ -1343,11 +1343,7 @@ impl<'a> Parser<'a> {
|
||||
self.parse_if_expr(attrs)
|
||||
} else if self.check_keyword(kw::For) {
|
||||
if self.choose_generics_over_qpath(1) {
|
||||
// NOTE(Centril, eddyb): DO NOT REMOVE! Beyond providing parser recovery,
|
||||
// this is an insurance policy in case we allow qpaths in (tuple-)struct patterns.
|
||||
// When `for <Foo as Bar>::Proj in $expr $block` is wanted,
|
||||
// you can disambiguate in favor of a pattern with `(...)`.
|
||||
self.recover_quantified_closure_expr(attrs)
|
||||
self.parse_closure_expr(attrs)
|
||||
} else {
|
||||
assert!(self.eat_keyword(kw::For));
|
||||
self.parse_for_expr(None, self.prev_token.span, attrs)
|
||||
@ -2094,30 +2090,22 @@ impl<'a> Parser<'a> {
|
||||
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()))
|
||||
}
|
||||
|
||||
/// Recover on an explicitly quantified closure expression, e.g., `for<'a> |x: &'a u8| *x + 1`.
|
||||
fn recover_quantified_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
let _ = self.parse_late_bound_lifetime_defs()?;
|
||||
let span_for = lo.to(self.prev_token.span);
|
||||
let closure = self.parse_closure_expr(attrs)?;
|
||||
|
||||
self.struct_span_err(span_for, "cannot introduce explicit parameters for a closure")
|
||||
.span_label(closure.span, "the parameters are attached to this closure")
|
||||
.span_suggestion(
|
||||
span_for,
|
||||
"remove the parameters",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
|
||||
Ok(self.mk_expr_err(lo.to(closure.span)))
|
||||
}
|
||||
|
||||
/// Parses a closure expression (e.g., `move |args| expr`).
|
||||
fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
|
||||
let binder = if self.check_keyword(kw::For) {
|
||||
let lo = self.token.span;
|
||||
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
||||
let span = lo.to(self.prev_token.span);
|
||||
|
||||
self.sess.gated_spans.gate(sym::closure_lifetime_binder, span);
|
||||
|
||||
ClosureBinder::For { span, generic_params: P::from_vec(lifetime_defs) }
|
||||
} else {
|
||||
ClosureBinder::NotPresent
|
||||
};
|
||||
|
||||
let movability =
|
||||
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
|
||||
|
||||
@ -2160,7 +2148,15 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let closure = self.mk_expr(
|
||||
lo.to(body.span),
|
||||
ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
|
||||
ExprKind::Closure(
|
||||
binder,
|
||||
capture_clause,
|
||||
asyncness,
|
||||
movability,
|
||||
decl,
|
||||
body,
|
||||
lo.to(decl_hi),
|
||||
),
|
||||
attrs,
|
||||
);
|
||||
|
||||
|
@ -259,7 +259,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
|
||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||
let parent_def = match expr.kind {
|
||||
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
|
||||
ExprKind::Closure(_, asyncness, ..) => {
|
||||
ExprKind::Closure(_, _, asyncness, ..) => {
|
||||
// Async closures desugar to closures inside of closures, so
|
||||
// we must create two defs.
|
||||
let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span);
|
||||
|
@ -3495,7 +3495,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
// `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
|
||||
// resolve the arguments within the proper scopes so that usages of them inside the
|
||||
// closure are detected as upvars rather than normal closure arg usages.
|
||||
ExprKind::Closure(_, Async::Yes { .. }, _, ref fn_decl, ref body, _span) => {
|
||||
ExprKind::Closure(_, _, Async::Yes { .. }, _, ref fn_decl, ref body, _span) => {
|
||||
self.with_rib(ValueNS, NormalRibKind, |this| {
|
||||
this.with_label_rib(ClosureOrAsyncRibKind, |this| {
|
||||
// Resolve arguments:
|
||||
|
@ -459,6 +459,7 @@ symbols! {
|
||||
clone_closures,
|
||||
clone_from,
|
||||
closure,
|
||||
closure_lifetime_binder,
|
||||
closure_to_fn_coercion,
|
||||
closure_track_caller,
|
||||
cmp,
|
||||
|
@ -114,6 +114,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
|
||||
let decl = P(FnDecl { inputs: vec![], output: FnRetTy::Default(DUMMY_SP) });
|
||||
iter_exprs(depth - 1, &mut |e| {
|
||||
g(ExprKind::Closure(
|
||||
ClosureBinder::NotPresent,
|
||||
CaptureBy::Value,
|
||||
Async::No,
|
||||
Movability::Movable,
|
||||
|
7
src/test/ui/closures/binder/async-closure-with-binder.rs
Normal file
7
src/test/ui/closures/binder/async-closure-with-binder.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// edition:2021
|
||||
#![feature(closure_lifetime_binder)]
|
||||
#![feature(async_closure)]
|
||||
fn main() {
|
||||
for<'a> async || ();
|
||||
//~^ ERROR `for<...>` binders on `async` closures are not currently supported
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
error: `for<...>` binders on `async` closures are not currently supported
|
||||
--> $DIR/async-closure-with-binder.rs:5:5
|
||||
|
|
||||
LL | for<'a> async || ();
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
6
src/test/ui/closures/binder/implicit-return.rs
Normal file
6
src/test/ui/closures/binder/implicit-return.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![feature(closure_lifetime_binder)]
|
||||
|
||||
fn main() {
|
||||
let _f = for<'a> |_: &'a ()| {};
|
||||
//~^ implicit return type is forbidden when `for<...>` is present
|
||||
}
|
10
src/test/ui/closures/binder/implicit-return.stderr
Normal file
10
src/test/ui/closures/binder/implicit-return.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: implicit return type is forbidden when `for<...>` is present
|
||||
--> $DIR/implicit-return.rs:4:34
|
||||
|
|
||||
LL | let _f = for<'a> |_: &'a ()| {};
|
||||
| ------- ^
|
||||
| |
|
||||
| `for<...>` is here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -0,0 +1,7 @@
|
||||
#![feature(closure_lifetime_binder)]
|
||||
fn main() {
|
||||
for<> |_: &'a ()| -> () {};
|
||||
//~^ ERROR use of undeclared lifetime name `'a`
|
||||
for<'a> |_: &'b ()| -> () {};
|
||||
//~^ ERROR use of undeclared lifetime name `'b`
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/suggestion-for-introducing-lifetime-into-binder.rs:3:16
|
||||
|
|
||||
LL | for<> |_: &'a ()| -> () {};
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
help: consider introducing lifetime `'a` here
|
||||
|
|
||||
LL | for<'a, > |_: &'a ()| -> () {};
|
||||
| +++
|
||||
help: consider introducing lifetime `'a` here
|
||||
|
|
||||
LL | fn main<'a>() {
|
||||
| ++++
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/suggestion-for-introducing-lifetime-into-binder.rs:5:18
|
||||
|
|
||||
LL | for<'a> |_: &'b ()| -> () {};
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
help: consider introducing lifetime `'b` here
|
||||
|
|
||||
LL | for<'b, 'a> |_: &'b ()| -> () {};
|
||||
| +++
|
||||
help: consider introducing lifetime `'b` here
|
||||
|
|
||||
LL | fn main<'b>() {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0261`.
|
@ -0,0 +1,12 @@
|
||||
fn main() {
|
||||
for<> || {};
|
||||
//~^ ERROR `for<...>` binders for closures are experimental
|
||||
//~^^ ERROR `for<...>` binders for closures are not yet supported
|
||||
for<'a> || {};
|
||||
//~^ ERROR `for<...>` binders for closures are experimental
|
||||
//~^^ ERROR `for<...>` binders for closures are not yet supported
|
||||
for<'a, 'b> |_: &'a ()| {};
|
||||
//~^ ERROR `for<...>` binders for closures are experimental
|
||||
//~^^ ERROR `for<...>` binders for closures are not yet supported
|
||||
//~^^^ ERROR use of undeclared lifetime name `'a`
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:8:22
|
||||
|
|
||||
LL | fn main() {
|
||||
| - help: consider introducing lifetime `'a` here: `<'a>`
|
||||
...
|
||||
LL | for<'a, 'b> |_: &'a ()| {};
|
||||
| ^^ undeclared lifetime
|
||||
|
||||
error[E0658]: `for<...>` binders for closures are experimental
|
||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:2:5
|
||||
|
|
||||
LL | for<> || {};
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
|
||||
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
|
||||
= help: consider removing `for<...>`
|
||||
|
||||
error[E0658]: `for<...>` binders for closures are experimental
|
||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:5:5
|
||||
|
|
||||
LL | for<'a> || {};
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
|
||||
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
|
||||
= help: consider removing `for<...>`
|
||||
|
||||
error[E0658]: `for<...>` binders for closures are experimental
|
||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:8:5
|
||||
|
|
||||
LL | for<'a, 'b> |_: &'a ()| {};
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
|
||||
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
|
||||
= help: consider removing `for<...>`
|
||||
|
||||
error: `for<...>` binders for closures are not yet supported
|
||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:2:5
|
||||
|
|
||||
LL | for<> || {};
|
||||
| ^^^^^
|
||||
|
|
||||
= help: consider removing `for<...>`
|
||||
|
||||
error: `for<...>` binders for closures are not yet supported
|
||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:5:5
|
||||
|
|
||||
LL | for<'a> || {};
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: consider removing `for<...>`
|
||||
|
||||
error: `for<...>` binders for closures are not yet supported
|
||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:8:5
|
||||
|
|
||||
LL | for<'a, 'b> |_: &'a ()| {};
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: consider removing `for<...>`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0261, E0658.
|
||||
For more information about an error, try `rustc --explain E0261`.
|
Loading…
Reference in New Issue
Block a user