From c2dbd62c7c60cd4017c9d499101e40c129e4bc61 Mon Sep 17 00:00:00 2001 From: Maybe Waffle <waffle.lapkin@gmail.com> Date: Tue, 12 Jul 2022 13:34:24 +0400 Subject: [PATCH] Lower closure binders to hir & properly check them --- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 48 +++++++++++------- compiler/rustc_hir/src/hir.rs | 12 +++++ compiler/rustc_hir/src/intravisit.rs | 11 ++++- compiler/rustc_hir_pretty/src/lib.rs | 40 ++++++++++++++- compiler/rustc_lint/src/early.rs | 1 + compiler/rustc_resolve/src/late.rs | 49 ++++++++++++++++--- compiler/rustc_resolve/src/late/lifetimes.rs | 49 ++++++++++++++++++- .../binder/async-closure-with-binder.rs | 1 + .../binder/async-closure-with-binder.stderr | 10 +++- .../ui/closures/binder/implicit-return.rs | 2 +- .../ui/closures/binder/implicit-return.stderr | 2 +- .../feature-gate-closure_lifetime_binder.rs | 10 ++-- ...eature-gate-closure_lifetime_binder.stderr | 48 +++--------------- .../ui/parser/recover-quantified-closure.rs | 5 +- .../parser/recover-quantified-closure.stderr | 27 ++++------ 16 files changed, 214 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 327fc505e99..3f830acbf27 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -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) { match binder { ClosureBinder::NotPresent => {} - ClosureBinder::For { span: _, generic_params } => { + ClosureBinder::For { generic_params, span: _ } => { walk_list!(visitor, visit_generic_param, generic_params) } } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 7a35660b0af..995dc6aab55 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -609,6 +609,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `static |_task_context| -> <ret_ty> { body }`: let generator_kind = hir::ExprKind::Closure { + binder: &hir::ClosureBinder::Default, capture_clause, bound_generic_params: &[], fn_decl, @@ -842,15 +843,9 @@ 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 (binder_clause, generic_params) = self.lower_closure_binder(binder); - 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; this.current_item = Some(fn_decl_span); let mut generator_kind = None; @@ -865,15 +860,16 @@ 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 { + 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, } @@ -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( &mut self, binder: &ClosureBinder, @@ -928,17 +939,15 @@ 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(); + 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) }; @@ -976,13 +985,14 @@ 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 { + binder: binder_clause, capture_clause, bound_generic_params, fn_decl, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d60ac330ed1..2252dfd683a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1931,6 +1931,7 @@ pub enum ExprKind<'hir> { /// This may also be a generator literal or an `async block` as indicated by the /// `Option<Movability>`. Closure { + binder: &'hir ClosureBinder, capture_clause: CaptureBy, bound_generic_params: &'hir [GenericParam<'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)] pub struct Mod<'hir> { pub spans: ModSpans, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 531d9f14040..6eceef56b47 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -925,7 +925,7 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<' FnKind::ItemFn(_, 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); } ExprKind::Closure { + binder: _, bound_generic_params, ref fn_decl, body, @@ -1153,7 +1154,13 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) movability: _, } => { 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) => { walk_list!(visitor, visit_label, opt_label); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 50acb0270b0..5453f4a8c92 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -6,6 +6,7 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_hir as hir; +use rustc_hir::LifetimeParamKind; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term}; use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}; use rustc_span::source_map::SourceMap; @@ -1441,6 +1442,7 @@ impl<'a> State<'a> { self.bclose(expr.span); } hir::ExprKind::Closure { + binder, capture_clause, bound_generic_params, fn_decl, @@ -1448,7 +1450,7 @@ impl<'a> State<'a> { fn_decl_span: _, 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_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>( &mut self, prefix: &'static str, diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 6c9638400b2..87cb2651dd3 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -154,6 +154,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> self.check_id(closure_id); } } + run_early_pass!(self, check_fn_post, fk, span, id); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index caf6f8c8392..80186650fe8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -844,19 +844,30 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { this.in_func_body = previous_state; } } - FnKind::Closure(declaration, body) => { - // We do not have any explicit generic lifetime parameter. - // FIXME(rfc3216): Change when implementing `for<>` bounds on closures. + FnKind::Closure(binder, declaration, body) => { + this.visit_closure_binder(binder); + this.with_lifetime_rib( - LifetimeRibKind::AnonymousCreateParameter { - binder: fn_id, - report_in_path: false, + match binder { + // We do not have any explicit generic lifetime parameter. + ClosureBinder::NotPresent => { + LifetimeRibKind::AnonymousCreateParameter { + binder: fn_id, + report_in_path: false, + } + } + ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError, }, // Add each argument to the rib. |this| this.resolve_params(&declaration.inputs), ); 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), ); @@ -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) { debug!("visit_generic_arg({:?})", arg); 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 + 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::Async(..) => { self.with_label_rib(ClosureOrAsyncRibKind, |this| visit::walk_expr(this, expr)); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 557dbecfabe..547255498a0 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -571,7 +571,51 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, '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 (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = bound_generic_params @@ -584,6 +628,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { (pair, r) }) .unzip(); + + // FIXME: missing_named_lifetime_spots + self.map.late_bound_vars.insert(e.hir_id, binders); let scope = Scope::Binder { hir_id: e.hir_id, diff --git a/src/test/ui/closures/binder/async-closure-with-binder.rs b/src/test/ui/closures/binder/async-closure-with-binder.rs index b9ecbd9e5d6..4fa599d37cb 100644 --- a/src/test/ui/closures/binder/async-closure-with-binder.rs +++ b/src/test/ui/closures/binder/async-closure-with-binder.rs @@ -4,4 +4,5 @@ fn main() { for<'a> async || (); //~^ ERROR `for<...>` binders on `async` closures are not currently supported + //~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present } diff --git a/src/test/ui/closures/binder/async-closure-with-binder.stderr b/src/test/ui/closures/binder/async-closure-with-binder.stderr index 46420a17752..1d4628b1a49 100644 --- a/src/test/ui/closures/binder/async-closure-with-binder.stderr +++ b/src/test/ui/closures/binder/async-closure-with-binder.stderr @@ -4,5 +4,13 @@ error: `for<...>` binders on `async` closures are not currently supported 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 diff --git a/src/test/ui/closures/binder/implicit-return.rs b/src/test/ui/closures/binder/implicit-return.rs index 3aefbdcb299..d34e5721d91 100644 --- a/src/test/ui/closures/binder/implicit-return.rs +++ b/src/test/ui/closures/binder/implicit-return.rs @@ -2,5 +2,5 @@ fn main() { 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 } diff --git a/src/test/ui/closures/binder/implicit-return.stderr b/src/test/ui/closures/binder/implicit-return.stderr index 022a4e027b6..5bfb9711334 100644 --- a/src/test/ui/closures/binder/implicit-return.stderr +++ b/src/test/ui/closures/binder/implicit-return.stderr @@ -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 | LL | let _f = for<'a> |_: &'a ()| {}; diff --git a/src/test/ui/feature-gates/feature-gate-closure_lifetime_binder.rs b/src/test/ui/feature-gates/feature-gate-closure_lifetime_binder.rs index 1e2090186a6..b0b494fa3ff 100644 --- a/src/test/ui/feature-gates/feature-gate-closure_lifetime_binder.rs +++ b/src/test/ui/feature-gates/feature-gate-closure_lifetime_binder.rs @@ -1,12 +1,8 @@ fn main() { - for<> || {}; + for<> || -> () {}; //~^ 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 not yet supported - for<'a, 'b> |_: &'a ()| {}; + 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` } diff --git a/src/test/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr b/src/test/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr index 77ce6f9f2d6..aea5cfeed07 100644 --- a/src/test/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr +++ b/src/test/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr @@ -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 --> $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 @@ -18,9 +9,9 @@ LL | for<> || {}; = help: consider removing `for<...>` 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 @@ -28,40 +19,15 @@ LL | for<'a> || {}; = help: consider removing `for<...>` 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 = 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: aborting due to 3 previous errors -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`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/recover-quantified-closure.rs b/src/test/ui/parser/recover-quantified-closure.rs index a2bb7fde8ff..10af39b7007 100644 --- a/src/test/ui/parser/recover-quantified-closure.rs +++ b/src/test/ui/parser/recover-quantified-closure.rs @@ -1,8 +1,7 @@ fn main() { 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 not yet supported + //~^ ERROR `for<...>` binders for closures are experimental + //~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present } enum Foo { Bar } diff --git a/src/test/ui/parser/recover-quantified-closure.stderr b/src/test/ui/parser/recover-quantified-closure.stderr index 168307ea65a..39eec80f658 100644 --- a/src/test/ui/parser/recover-quantified-closure.stderr +++ b/src/test/ui/parser/recover-quantified-closure.stderr @@ -1,17 +1,9 @@ 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 {} | ^^ 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 --> $DIR/recover-quantified-closure.rs:2:5 | @@ -23,7 +15,7 @@ LL | for<'a> |x: &'a u8| *x + 1; = help: consider removing `for<...>` 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 {} | ^^^^^^^^^ @@ -32,15 +24,14 @@ LL | for <Foo>::Bar in x {} = 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/recover-quantified-closure.rs:2:5 +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/recover-quantified-closure.rs:2:25 | 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 an error, try `rustc --explain E0261`. +For more information about this error, try `rustc --explain E0658`.