Lower closure binders to hir & properly check them
This commit is contained in:
parent
f89ef3cf66
commit
c2dbd62c7c
16 changed files with 214 additions and 103 deletions
|
@ -642,7 +642,7 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics
|
||||||
pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a ClosureBinder) {
|
pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a ClosureBinder) {
|
||||||
match binder {
|
match binder {
|
||||||
ClosureBinder::NotPresent => {}
|
ClosureBinder::NotPresent => {}
|
||||||
ClosureBinder::For { span: _, generic_params } => {
|
ClosureBinder::For { generic_params, span: _ } => {
|
||||||
walk_list!(visitor, visit_generic_param, generic_params)
|
walk_list!(visitor, visit_generic_param, generic_params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -609,6 +609,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
// `static |_task_context| -> <ret_ty> { body }`:
|
// `static |_task_context| -> <ret_ty> { body }`:
|
||||||
let generator_kind = hir::ExprKind::Closure {
|
let generator_kind = hir::ExprKind::Closure {
|
||||||
|
binder: &hir::ClosureBinder::Default,
|
||||||
capture_clause,
|
capture_clause,
|
||||||
bound_generic_params: &[],
|
bound_generic_params: &[],
|
||||||
fn_decl,
|
fn_decl,
|
||||||
|
@ -842,15 +843,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
body: &Expr,
|
body: &Expr,
|
||||||
fn_decl_span: Span,
|
fn_decl_span: Span,
|
||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::ExprKind<'hir> {
|
||||||
// FIXME(waffle): lower binder
|
let (binder_clause, generic_params) = self.lower_closure_binder(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 (body_id, generator_option) = self.with_new_scopes(move |this| {
|
||||||
let prev = this.current_item;
|
let prev = this.current_item;
|
||||||
this.current_item = Some(fn_decl_span);
|
this.current_item = Some(fn_decl_span);
|
||||||
let mut generator_kind = None;
|
let mut generator_kind = None;
|
||||||
|
@ -865,15 +860,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
(body_id, generator_option)
|
(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`.
|
// Lower outside new scope to preserve `is_in_loop_condition`.
|
||||||
let fn_decl = this.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
|
let fn_decl = this.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
|
||||||
|
|
||||||
hir::ExprKind::Closure {
|
hir::ExprKind::Closure {
|
||||||
|
binder: binder_clause,
|
||||||
capture_clause,
|
capture_clause,
|
||||||
bound_generic_params,
|
bound_generic_params,
|
||||||
fn_decl,
|
fn_decl,
|
||||||
body,
|
body: body_id,
|
||||||
fn_decl_span: this.lower_span(fn_decl_span),
|
fn_decl_span: this.lower_span(fn_decl_span),
|
||||||
movability: generator_option,
|
movability: generator_option,
|
||||||
}
|
}
|
||||||
|
@ -918,6 +914,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_closure_binder<'c>(
|
||||||
|
&mut self,
|
||||||
|
binder: &'c ClosureBinder,
|
||||||
|
) -> (&'hir 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)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(self.arena.alloc(binder), params)
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_expr_async_closure(
|
fn lower_expr_async_closure(
|
||||||
&mut self,
|
&mut self,
|
||||||
binder: &ClosureBinder,
|
binder: &ClosureBinder,
|
||||||
|
@ -928,17 +939,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
body: &Expr,
|
body: &Expr,
|
||||||
fn_decl_span: Span,
|
fn_decl_span: Span,
|
||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::ExprKind<'hir> {
|
||||||
// FIXME(waffle): lower binder
|
|
||||||
if let &ClosureBinder::For { span, .. } = binder {
|
if let &ClosureBinder::For { span, .. } = binder {
|
||||||
self.sess
|
self.tcx.sess.span_err(
|
||||||
.struct_span_err(
|
span,
|
||||||
span,
|
"`for<...>` binders on `async` closures are not currently supported",
|
||||||
"`for<...>` binders for async closures are not yet supported",
|
);
|
||||||
)
|
|
||||||
.help("consider removing `for<...>`")
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||||
|
|
||||||
let outer_decl =
|
let outer_decl =
|
||||||
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
||||||
|
|
||||||
|
@ -976,13 +985,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
body_id
|
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
|
// 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
|
// have to conserve the state of being inside a loop condition for the
|
||||||
// closure argument types.
|
// closure argument types.
|
||||||
let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
|
let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
|
||||||
|
|
||||||
hir::ExprKind::Closure {
|
hir::ExprKind::Closure {
|
||||||
|
binder: binder_clause,
|
||||||
capture_clause,
|
capture_clause,
|
||||||
bound_generic_params,
|
bound_generic_params,
|
||||||
fn_decl,
|
fn_decl,
|
||||||
|
|
|
@ -1931,6 +1931,7 @@ pub enum ExprKind<'hir> {
|
||||||
/// This may also be a generator literal or an `async block` as indicated by the
|
/// This may also be a generator literal or an `async block` as indicated by the
|
||||||
/// `Option<Movability>`.
|
/// `Option<Movability>`.
|
||||||
Closure {
|
Closure {
|
||||||
|
binder: &'hir ClosureBinder,
|
||||||
capture_clause: CaptureBy,
|
capture_clause: CaptureBy,
|
||||||
bound_generic_params: &'hir [GenericParam<'hir>],
|
bound_generic_params: &'hir [GenericParam<'hir>],
|
||||||
fn_decl: &'hir FnDecl<'hir>,
|
fn_decl: &'hir FnDecl<'hir>,
|
||||||
|
@ -2715,6 +2716,17 @@ impl FnRetTy<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents `for<...>` binder before a closure
|
||||||
|
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
||||||
|
pub enum ClosureBinder {
|
||||||
|
/// Binder is not specified.
|
||||||
|
Default,
|
||||||
|
/// Binder is specified.
|
||||||
|
///
|
||||||
|
/// Span points to the whole `for<...>`.
|
||||||
|
For { span: Span },
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Encodable, Debug, HashStable_Generic)]
|
#[derive(Encodable, Debug, HashStable_Generic)]
|
||||||
pub struct Mod<'hir> {
|
pub struct Mod<'hir> {
|
||||||
pub spans: ModSpans,
|
pub spans: ModSpans,
|
||||||
|
|
|
@ -925,7 +925,7 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
|
||||||
FnKind::ItemFn(_, generics, ..) => {
|
FnKind::ItemFn(_, generics, ..) => {
|
||||||
visitor.visit_generics(generics);
|
visitor.visit_generics(generics);
|
||||||
}
|
}
|
||||||
FnKind::Method(..) | FnKind::Closure => {}
|
FnKind::Closure | FnKind::Method(..) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,6 +1145,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
||||||
walk_list!(visitor, visit_arm, arms);
|
walk_list!(visitor, visit_arm, arms);
|
||||||
}
|
}
|
||||||
ExprKind::Closure {
|
ExprKind::Closure {
|
||||||
|
binder: _,
|
||||||
bound_generic_params,
|
bound_generic_params,
|
||||||
ref fn_decl,
|
ref fn_decl,
|
||||||
body,
|
body,
|
||||||
|
@ -1153,7 +1154,13 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
||||||
movability: _,
|
movability: _,
|
||||||
} => {
|
} => {
|
||||||
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||||
visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
|
visitor.visit_fn(
|
||||||
|
FnKind::Closure,
|
||||||
|
fn_decl,
|
||||||
|
body,
|
||||||
|
expression.span,
|
||||||
|
expression.hir_id,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ExprKind::Block(ref block, ref opt_label) => {
|
ExprKind::Block(ref block, ref opt_label) => {
|
||||||
walk_list!(visitor, visit_label, opt_label);
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
|
|
|
@ -6,6 +6,7 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
|
||||||
use rustc_ast_pretty::pp::{self, Breaks};
|
use rustc_ast_pretty::pp::{self, Breaks};
|
||||||
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::LifetimeParamKind;
|
||||||
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term};
|
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term};
|
||||||
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
|
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
|
||||||
use rustc_span::source_map::SourceMap;
|
use rustc_span::source_map::SourceMap;
|
||||||
|
@ -1441,6 +1442,7 @@ impl<'a> State<'a> {
|
||||||
self.bclose(expr.span);
|
self.bclose(expr.span);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Closure {
|
hir::ExprKind::Closure {
|
||||||
|
binder,
|
||||||
capture_clause,
|
capture_clause,
|
||||||
bound_generic_params,
|
bound_generic_params,
|
||||||
fn_decl,
|
fn_decl,
|
||||||
|
@ -1448,7 +1450,7 @@ impl<'a> State<'a> {
|
||||||
fn_decl_span: _,
|
fn_decl_span: _,
|
||||||
movability: _,
|
movability: _,
|
||||||
} => {
|
} => {
|
||||||
self.print_formal_generic_params(bound_generic_params);
|
self.print_closure_binder(binder, bound_generic_params);
|
||||||
self.print_capture_clause(capture_clause);
|
self.print_capture_clause(capture_clause);
|
||||||
|
|
||||||
self.print_closure_params(fn_decl, body);
|
self.print_closure_params(fn_decl, body);
|
||||||
|
@ -2033,6 +2035,42 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_closure_binder(
|
||||||
|
&mut self,
|
||||||
|
binder: &hir::ClosureBinder,
|
||||||
|
generic_params: &[GenericParam<'_>],
|
||||||
|
) {
|
||||||
|
let generic_params = generic_params
|
||||||
|
.iter()
|
||||||
|
.filter(|p| {
|
||||||
|
matches!(
|
||||||
|
p,
|
||||||
|
GenericParam {
|
||||||
|
kind: GenericParamKind::Lifetime { kind: LifetimeParamKind::Explicit },
|
||||||
|
..
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
match binder {
|
||||||
|
hir::ClosureBinder::Default => {}
|
||||||
|
// we need to distinguish `|...| {}` from `for<> |...| {}` as `for<>` adds additional restrictions
|
||||||
|
hir::ClosureBinder::For { .. } if generic_params.is_empty() => self.word("for<>"),
|
||||||
|
hir::ClosureBinder::For { .. } => {
|
||||||
|
self.word("for");
|
||||||
|
self.word("<");
|
||||||
|
|
||||||
|
self.commasep(Inconsistent, &generic_params, |s, param| {
|
||||||
|
s.print_generic_param(param)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.word(">");
|
||||||
|
self.nbsp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_bounds<'b>(
|
pub fn print_bounds<'b>(
|
||||||
&mut self,
|
&mut self,
|
||||||
prefix: &'static str,
|
prefix: &'static str,
|
||||||
|
|
|
@ -154,6 +154,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
||||||
self.check_id(closure_id);
|
self.check_id(closure_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run_early_pass!(self, check_fn_post, fk, span, id);
|
run_early_pass!(self, check_fn_post, fk, span, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -844,19 +844,30 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
this.in_func_body = previous_state;
|
this.in_func_body = previous_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FnKind::Closure(declaration, body) => {
|
FnKind::Closure(binder, declaration, body) => {
|
||||||
// We do not have any explicit generic lifetime parameter.
|
this.visit_closure_binder(binder);
|
||||||
// FIXME(rfc3216): Change when implementing `for<>` bounds on closures.
|
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousCreateParameter {
|
match binder {
|
||||||
binder: fn_id,
|
// We do not have any explicit generic lifetime parameter.
|
||||||
report_in_path: false,
|
ClosureBinder::NotPresent => {
|
||||||
|
LifetimeRibKind::AnonymousCreateParameter {
|
||||||
|
binder: fn_id,
|
||||||
|
report_in_path: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
|
||||||
},
|
},
|
||||||
// Add each argument to the rib.
|
// Add each argument to the rib.
|
||||||
|this| this.resolve_params(&declaration.inputs),
|
|this| this.resolve_params(&declaration.inputs),
|
||||||
);
|
);
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousPassThrough(fn_id, true),
|
match binder {
|
||||||
|
ClosureBinder::NotPresent => {
|
||||||
|
LifetimeRibKind::AnonymousPassThrough(fn_id, true)
|
||||||
|
}
|
||||||
|
ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
|
||||||
|
},
|
||||||
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -891,6 +902,18 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) {
|
||||||
|
match b {
|
||||||
|
ClosureBinder::NotPresent => {}
|
||||||
|
ClosureBinder::For { generic_params, .. } => {
|
||||||
|
self.visit_generic_params(
|
||||||
|
&generic_params,
|
||||||
|
self.diagnostic_metadata.current_self_item.is_some(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
|
fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
|
||||||
debug!("visit_generic_arg({:?})", arg);
|
debug!("visit_generic_arg({:?})", arg);
|
||||||
let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true);
|
let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true);
|
||||||
|
@ -3515,6 +3538,18 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// For closures, ClosureOrAsyncRibKind is added in visit_fn
|
// For closures, ClosureOrAsyncRibKind is added in visit_fn
|
||||||
|
ExprKind::Closure(ClosureBinder::For { ref generic_params, span }, ..) => {
|
||||||
|
self.with_generic_param_rib(
|
||||||
|
&generic_params,
|
||||||
|
NormalRibKind,
|
||||||
|
LifetimeRibKind::Generics {
|
||||||
|
binder: expr.id,
|
||||||
|
kind: LifetimeBinderKind::Function,
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
|this| visit::walk_expr(this, expr),
|
||||||
|
);
|
||||||
|
}
|
||||||
ExprKind::Closure(..) => visit::walk_expr(self, expr),
|
ExprKind::Closure(..) => visit::walk_expr(self, expr),
|
||||||
ExprKind::Async(..) => {
|
ExprKind::Async(..) => {
|
||||||
self.with_label_rib(ClosureOrAsyncRibKind, |this| visit::walk_expr(this, expr));
|
self.with_label_rib(ClosureOrAsyncRibKind, |this| visit::walk_expr(this, expr));
|
||||||
|
|
|
@ -571,7 +571,51 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
|
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
|
||||||
if let hir::ExprKind::Closure { bound_generic_params, .. } = e.kind {
|
if let hir::ExprKind::Closure { binder, bound_generic_params, fn_decl, .. } = e.kind {
|
||||||
|
if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
|
||||||
|
fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
|
||||||
|
struct V(Option<Span>);
|
||||||
|
|
||||||
|
impl<'v> Visitor<'v> for V {
|
||||||
|
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
|
||||||
|
match t.kind {
|
||||||
|
_ if self.0.is_some() => (),
|
||||||
|
hir::TyKind::Infer => {
|
||||||
|
self.0 = Some(t.span);
|
||||||
|
}
|
||||||
|
_ => intravisit::walk_ty(self, t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut v = V(None);
|
||||||
|
v.visit_ty(ty);
|
||||||
|
v.0
|
||||||
|
}
|
||||||
|
|
||||||
|
let infer_in_rt_sp = match fn_decl.output {
|
||||||
|
hir::FnRetTy::DefaultReturn(sp) => Some(sp),
|
||||||
|
hir::FnRetTy::Return(ty) => span_of_infer(ty),
|
||||||
|
};
|
||||||
|
|
||||||
|
let infer_spans = fn_decl
|
||||||
|
.inputs
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(span_of_infer)
|
||||||
|
.chain(infer_in_rt_sp)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if !infer_spans.is_empty() {
|
||||||
|
self.tcx.sess
|
||||||
|
.struct_span_err(
|
||||||
|
infer_spans,
|
||||||
|
"implicit types in closure signatures are forbidden when `for<...>` is present",
|
||||||
|
)
|
||||||
|
.span_label(for_sp, "`for<...>` is here")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let next_early_index = self.next_early_index();
|
let next_early_index = self.next_early_index();
|
||||||
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
|
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
|
||||||
bound_generic_params
|
bound_generic_params
|
||||||
|
@ -584,6 +628,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
(pair, r)
|
(pair, r)
|
||||||
})
|
})
|
||||||
.unzip();
|
.unzip();
|
||||||
|
|
||||||
|
// FIXME: missing_named_lifetime_spots
|
||||||
|
|
||||||
self.map.late_bound_vars.insert(e.hir_id, binders);
|
self.map.late_bound_vars.insert(e.hir_id, binders);
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
hir_id: e.hir_id,
|
hir_id: e.hir_id,
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
for<'a> async || ();
|
for<'a> async || ();
|
||||||
//~^ ERROR `for<...>` binders on `async` closures are not currently supported
|
//~^ ERROR `for<...>` binders on `async` closures are not currently supported
|
||||||
|
//~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,13 @@ error: `for<...>` binders on `async` closures are not currently supported
|
||||||
LL | for<'a> async || ();
|
LL | for<'a> async || ();
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: implicit types in closure signatures are forbidden when `for<...>` is present
|
||||||
|
--> $DIR/async-closure-with-binder.rs:5:5
|
||||||
|
|
|
||||||
|
LL | for<'a> async || ();
|
||||||
|
| -------^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| `for<...>` is here
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _f = for<'a> |_: &'a ()| {};
|
let _f = for<'a> |_: &'a ()| {};
|
||||||
//~^ implicit return type is forbidden when `for<...>` is present
|
//~^ implicit types in closure signatures are forbidden when `for<...>` is present
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: implicit return type is forbidden when `for<...>` is present
|
error: implicit types in closure signatures are forbidden when `for<...>` is present
|
||||||
--> $DIR/implicit-return.rs:4:34
|
--> $DIR/implicit-return.rs:4:34
|
||||||
|
|
|
|
||||||
LL | let _f = for<'a> |_: &'a ()| {};
|
LL | let _f = for<'a> |_: &'a ()| {};
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
for<> || {};
|
for<> || -> () {};
|
||||||
//~^ ERROR `for<...>` binders for closures are experimental
|
//~^ ERROR `for<...>` binders for closures are experimental
|
||||||
//~^^ ERROR `for<...>` binders for closures are not yet supported
|
for<'a> || -> () {};
|
||||||
for<'a> || {};
|
|
||||||
//~^ ERROR `for<...>` binders for closures are experimental
|
//~^ ERROR `for<...>` binders for closures are experimental
|
||||||
//~^^ ERROR `for<...>` binders for closures are not yet supported
|
for<'a, 'b> |_: &'a ()| -> () {};
|
||||||
for<'a, 'b> |_: &'a ()| {};
|
|
||||||
//~^ ERROR `for<...>` binders for closures are experimental
|
//~^ ERROR `for<...>` binders for closures are experimental
|
||||||
//~^^ ERROR `for<...>` binders for closures are not yet supported
|
|
||||||
//~^^^ ERROR use of undeclared lifetime name `'a`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,7 @@
|
||||||
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
|
error[E0658]: `for<...>` binders for closures are experimental
|
||||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:2:5
|
--> $DIR/feature-gate-closure_lifetime_binder.rs:2:5
|
||||||
|
|
|
|
||||||
LL | for<> || {};
|
LL | for<> || -> () {};
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
|
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
|
||||||
|
@ -18,9 +9,9 @@ LL | for<> || {};
|
||||||
= help: consider removing `for<...>`
|
= help: consider removing `for<...>`
|
||||||
|
|
||||||
error[E0658]: `for<...>` binders for closures are experimental
|
error[E0658]: `for<...>` binders for closures are experimental
|
||||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:5:5
|
--> $DIR/feature-gate-closure_lifetime_binder.rs:4:5
|
||||||
|
|
|
|
||||||
LL | for<'a> || {};
|
LL | for<'a> || -> () {};
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
|
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
|
||||||
|
@ -28,40 +19,15 @@ LL | for<'a> || {};
|
||||||
= help: consider removing `for<...>`
|
= help: consider removing `for<...>`
|
||||||
|
|
||||||
error[E0658]: `for<...>` binders for closures are experimental
|
error[E0658]: `for<...>` binders for closures are experimental
|
||||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:8:5
|
--> $DIR/feature-gate-closure_lifetime_binder.rs:6:5
|
||||||
|
|
|
|
||||||
LL | for<'a, 'b> |_: &'a ()| {};
|
LL | for<'a, 'b> |_: &'a ()| -> () {};
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
|
= 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: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
|
||||||
= help: consider removing `for<...>`
|
= help: consider removing `for<...>`
|
||||||
|
|
||||||
error: `for<...>` binders for closures are not yet supported
|
error: aborting due to 3 previous errors
|
||||||
--> $DIR/feature-gate-closure_lifetime_binder.rs:2:5
|
|
||||||
|
|
|
||||||
LL | for<> || {};
|
|
||||||
| ^^^^^
|
|
||||||
|
|
|
||||||
= help: consider removing `for<...>`
|
|
||||||
|
|
||||||
error: `for<...>` binders for closures are not yet supported
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
--> $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`.
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
for<'a> |x: &'a u8| *x + 1;
|
for<'a> |x: &'a u8| *x + 1;
|
||||||
//~^ ERROR use of undeclared lifetime name `'a`
|
//~^ ERROR `for<...>` binders for closures are experimental
|
||||||
//~^^ ERROR `for<...>` binders for closures are experimental
|
//~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
|
||||||
//~^^^ ERROR `for<...>` binders for closures are not yet supported
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Foo { Bar }
|
enum Foo { Bar }
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
error: expected one of `move`, `static`, `|`, or `||`, found `::`
|
error: expected one of `move`, `static`, `|`, or `||`, found `::`
|
||||||
--> $DIR/recover-quantified-closure.rs:10:14
|
--> $DIR/recover-quantified-closure.rs:9:14
|
||||||
|
|
|
|
||||||
LL | for <Foo>::Bar in x {}
|
LL | for <Foo>::Bar in x {}
|
||||||
| ^^ expected one of `move`, `static`, `|`, or `||`
|
| ^^ expected one of `move`, `static`, `|`, or `||`
|
||||||
|
|
||||||
error[E0261]: use of undeclared lifetime name `'a`
|
|
||||||
--> $DIR/recover-quantified-closure.rs:2:18
|
|
||||||
|
|
|
||||||
LL | fn main() {
|
|
||||||
| - help: consider introducing lifetime `'a` here: `<'a>`
|
|
||||||
LL | for<'a> |x: &'a u8| *x + 1;
|
|
||||||
| ^^ undeclared lifetime
|
|
||||||
|
|
||||||
error[E0658]: `for<...>` binders for closures are experimental
|
error[E0658]: `for<...>` binders for closures are experimental
|
||||||
--> $DIR/recover-quantified-closure.rs:2:5
|
--> $DIR/recover-quantified-closure.rs:2:5
|
||||||
|
|
|
|
||||||
|
@ -23,7 +15,7 @@ LL | for<'a> |x: &'a u8| *x + 1;
|
||||||
= help: consider removing `for<...>`
|
= help: consider removing `for<...>`
|
||||||
|
|
||||||
error[E0658]: `for<...>` binders for closures are experimental
|
error[E0658]: `for<...>` binders for closures are experimental
|
||||||
--> $DIR/recover-quantified-closure.rs:10:5
|
--> $DIR/recover-quantified-closure.rs:9:5
|
||||||
|
|
|
|
||||||
LL | for <Foo>::Bar in x {}
|
LL | for <Foo>::Bar in x {}
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -32,15 +24,14 @@ LL | for <Foo>::Bar in x {}
|
||||||
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
|
= help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
|
||||||
= help: consider removing `for<...>`
|
= help: consider removing `for<...>`
|
||||||
|
|
||||||
error: `for<...>` binders for closures are not yet supported
|
error: implicit types in closure signatures are forbidden when `for<...>` is present
|
||||||
--> $DIR/recover-quantified-closure.rs:2:5
|
--> $DIR/recover-quantified-closure.rs:2:25
|
||||||
|
|
|
|
||||||
LL | for<'a> |x: &'a u8| *x + 1;
|
LL | for<'a> |x: &'a u8| *x + 1;
|
||||||
| ^^^^^^^
|
| ------- ^
|
||||||
|
|
| |
|
||||||
= help: consider removing `for<...>`
|
| `for<...>` is here
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0261, E0658.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
For more information about an error, try `rustc --explain E0261`.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue